SAS — добавить строковую макропеременную к имени набора данных

Я пытаюсь добавить строковую макропеременную к имени набора данных в SAS. Я хочу создать наборы данных, которые читаются как work.cps2020jan и work.cps2020feb. Но это не то, что я получаю. Мой код:

%macro loop(values); 
 
     %let count=%sysfunc(countw(&values));

     %do i = 1 %to &count;                                           
      %let value=%qscan(&values,&i,%str(,));                                                                                          
      %put &value; 

    data work.cps2020&value.;
        set "A:\cpsb2020&value" ;

    mth = "&value.";

    keep
    PEMLR 
    mth
    ;

    run;

    %end;                                                                                                                      
                                                                                                                              
%mend;
                         
%loop(%str(jan,feb)); 

Запуск этого кода приводит к следующему выводу в журнале:

NOTE: There were 138697 observations read from the data set
      A:\cpsb2020jan.
NOTE: The data set WORK.CPS2020 has 138697 observations and 2 variables.
NOTE: The data set WORK.JAN has 138697 observations and 2 variables.
NOTE: DATA statement used (Total process time):
      real time           4.29 seconds
      cpu time            0.20 seconds


feb

NOTE: There were 139248 observations read from the data set
      A:\cpsb2020feb.
NOTE: The data set WORK.CPS2020 has 139248 observations and 2 variables.
NOTE: The data set WORK.FEB has 139248 observations and 2 variables.
NOTE: DATA statement used (Total process time):
      real time           4.44 seconds
      cpu time            0.15 seconds

Я не понимаю, почему мой макрос создает два набора данных на цикл вместо одного набора данных на цикл с именами work.cps2020jan и work.cps2020feb. Если я изменю &value. к &i. SAS выводит work.cps20201 и work.cps20202. Но это не то, чего я хочу.

Любые идеи?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
793
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

&value возвращается, как указано %qscan(). Вместо этого используйте %scan(). Переменные макроса в кавычках могут иногда вызывать проблемы при разрешении, когда они используются таким образом. Лучше цитировать их только тогда, когда это необходимо, например, в выражении %put со знаком % внутри него.

Вам не нужно %qscan(). Если бы значение содержало какие-либо символы, требующие заключения макроса в кавычки, то они в любом случае были бы недопустимы для использования в имени члена. Так что используйте %scan() вместо этого.

Но при использовании внутри макроса токенизатор иногда ошибочно воспринимает такие вещи, как xxx&mvar, как два токена, даже если в &mvar нет специальных символов. Вы можете сгруппировать значение, которое вы создаете, чтобы обойти это.

Например, создав новую макропеременную

%let dsn=cps2020&value.;
data work.&dsn. ;

Или используйте функцию %unquote():

data %unquote(work.cps2020&value.);

Или используйте литерал имени:

data work."cps2020&value."n;
Ответ принят как подходящий

Функция макроса %QSCAN замаскирует результат специальными невидимыми (непечатаемыми) символами, видимыми только для системы макропроцессора.

Что случилось, так это

data work.cps2020&value.;

рассматривался как

data work.cps2020<mask-character><non-masked part of symbol value><mask-character>;  

во время обработки исполнителем, который обрабатывал непечатаемый символ маски как несинтаксический разделитель токенов, в результате чего был получен оператор DATA со списком двух выходных таблиц.

data work.cps2020 jan;

Положения символов маски в макропеременной можно наблюдать (в журнале) с помощью %put _user_, или фактическое содержимое символа можно захватить из представления метаданных, такого как SASHELP.VMACRO или DICTIONARY.MACRO

Давайте упростим ваш макрос и добавим журналирование и захват символов

%macro loop(values); 
  %local count i;

  %let count=%sysfunc(countw(&values));
  %do i = 1 %to &count;
    %let value=%qscan(&values,&i,%str(,));

    %put _user_;                   %*--- log them masks;

    data x&i;                      %* --- symbol capture;
      set sashelp.vmacro;
      where name like '%VALUE%';
      value_hex = put (value,$HEX40.);
    run;

    %* --- do the step that creates two tables;

    data work.cps2020&value.;
      set sashelp.class;
    run;
  %end;
%mend;

options nomprint nosymbolgen nomlogic;

%loop(%str(jan,feb));

proc print data=x1 noobs style(data)=[fontsize=14pt fontfamily = "Courier"];
  var value:;
run;

Фрагмент LOG, эти маленькие прямоугольники представляют собой специальные невидимые маскирующие символы (я показываю их на снимках изображений, потому что переполнение стека / html не отображает непечатаемые символы)

Тот же текст LOG, скопированный и вставленный в Notepad2, показывает символы маски как управляющие символы

Proc PRINT захваченных данных символа макроса будет отображать шестнадцатеричные маскирующие символы.

  • 06 запуск макроса %quote
  • 08 макрос %quote конец
  • 01 запуск макроса %str
  • 02 макрос %str конец
  • 1E скрытая версия запятой

Отличное объяснение

Stu Sztukowski 13.12.2020 18:10

Вау - это было здорово, спасибо! После замены qscan() на scan() макрос сделал то, что я хотел (перебрать список строк и добавить строку к имени набора данных).

jonathan63 16.12.2020 20:36

Другие вопросы по теме