2016-08-26 2 views
0

Я пытаюсь использовать цикл% DO для добавления нескольких ежемесячных файлов данных. Вот код, который я до сих пор:SAS% DO Loop для извлечения нескольких наборов данных

options mprint symbolgen source mlogic merror syntaxcheck ; 


%MACRO INT; 

%DO i=01 %TO 03 %BY 1; 

libname appd "Qual1.Qual2.Qual3.QUAL416&i." disp=shr; 

data work&i.; 
set appd.file; 
run; 

data final; 
set work; 
run; 

proc append data=work&i. 
      base=final; 
run; 

%MEND; 

%INT; 

Я получаю сообщение об ошибке:

ПРЕДУПРЕЖДЕНИЕ: Строка в кавычках в данный момент обрабатывается стала более , чем 262 символов. У вас может быть несбалансированная котировка марок.

Я никогда не получал эту ошибку раньше, и я не совсем уверен, что это значит. Я пытаюсь создать этот макрос, чтобы добавить несколько файлов с этого года, но в идеале он будет охватывать несколько лет. т. е. изменение mtro16 & i. к mtro & i. ЗА ИСКЛЮЧЕНИЕМ Я не хочу, чтобы код %DO i=1601 %TO 1612 %BY 1 явно, потому что мне придется менять его на каждый год, например. если я начну в 2010 году, мне придется писать код 2010, затем отдельный отчет %DO за 2011 год и т. д. до 2016 года. Это не похоже на много, но через десятилетие> + это может быть.

UPDATE: Я изменил код, чтобы включить этот бит:

`%DO i=1005 %TO 1607; 
%IF i=1013 %THEN %DO i=1101 %TO 1112; 
/*%ELSE %IF i=1113 %THEN %DO i=1201 %TO 1212;*/ 
/*%ELSE %IF i=1213 %THEN %DO i=1301 %TO 1312;*/ 
/*%ELSE %IF i=1313 %THEN %DO i=1401 %TO 1412;*/ 
/*%ELSE %IF i=1413 %THEN %DO i= 1501 %TO 1512;*/ 
/*%ELSE %IF i=1513 %THEN %DO i=1601 %TO 1607;*/` 

Это своего рода Janky, но я думал, что это будет работать только петлю до конца года, а затем начать следующую итерацию после i=1012 to i=1101 , Тем не менее, это то, что происходит в моем журнале:

MLOGIC(INT): %DO loop index variable I is now 1012; loop will iterate again. 
MLOGIC(INT): %IF condition i=1013 is FALSE 
MLOGIC(INT): %DO loop index variable I is now 1013; loop will iterate again. 
MLOGIC(INT): %IF condition i=1013 is FALSE 

Как SAS лечения этого %IF состояние? Он говорит мне, что переменная i = 1013 и что %IF условие i=1013 ЛОЖНО? Почему это не ИСТИНА?

+0

Я обычно получаю такого рода предупреждение при создании макропеременной, устраняющей в строку и сама строка имеет более указанные символы. Он может быть абсолютно корректным и работать нормально, но SAS думает, что может возникнуть проблема, поскольку он не предназначен для ожидания строк до тех пор, пока это не будет. Если код сделает так, как ожидалось, я бы не стал беспокоиться об этом, так как я не думаю, что вы можете остановить его от создания предупреждения. Тем не менее, у вас нет% конца; закрыть свою петлю, чтобы она просто конкатенировала их все вместе? –

+0

SMH. Я пропущу их все время – DukeLuke

+1

Кроме того, переменная 01 в вашей инструкции do решит 1 в макросе при вызове. поэтому вы получите mtro161 через mtro163. Вам нужно будет добавить что-то вроде длины if <2, а затем j = strip (0 || i), чтобы связать подозрительный вывод с первым нулем, а затем создать ваше имя mtro16 & j. вместо. –

ответ

2

Я думаю, когда работая с датами, вы всегда должны работать с значениями даты, а не пытаться использовать ярлыки, используя годы или месяцы или другие подобные «ярлыки». По моему опыту, они всегда приводят к запутывающему или ошибочному коду.

Ниже приведен макрос, который показывает, как вы можете передать дату начала и дату окончания (это даже не должно быть 1-го числа месяца), и оно вернет соответствующие ежемесячные имена. Затем вы можете адаптировать это для работы с вашим proc append или другим кодом по своему усмотрению.

Это фактически принимает 2 Дата значения как параметры. Затем он использует цикл %do %while и функцию intnx() для циклического перехода от даты начала до даты окончания 1 месяц за раз. Я использую %sysfunc(sum(),yymmn4.) для расчета желаемого формата для ваших ежемесячных наборов данных и печати его в журнал.

Код:

%macro append_monthly(iStart_date=, iEnd_date=); 

    %local tmp_date id; 
    %let tmp_date = %sysfunc(intnx(month,&iStart_date,0,beginning)) ; 

    %do %while (&tmp_date le &iEnd_date); 

    %let id = %sysfunc(sum(&tmp_date),yymmn4.); 
    %put &=id; 

    %let tmp_date = %sysfunc(intnx(month,&tmp_date,1,beginning)) ; 

    %end; 

%mend; 
%append_monthly(iStart_date=%sysfunc(mdy(1,1,2010)), iEnd_date=%sysfunc(mdy(1,1,2013))); 

Обратите внимание, что %sysfunc(sum(&tmp_date),yymmn4.) является своего рода ярлыком при использовании макросов форматирования числа.%sysfunc() требует от нас функции в качестве первого параметра, и вы можете опционально предоставить формат в качестве второго параметра. Функция sum() удобна, так как она не меняет числовое значение.

Выход:

ID=1001 
ID=1002 
ID=1003 
... 
ID=1011 
ID=1012 
ID=1101 
ID=1102 
ID=1103 
... 
ID=1110 
ID=1111 
ID=1112 
ID=1201 
ID=1202 
ID=1203 
... 
ID=1210 
ID=1211 
ID=1212 
ID=1301 
+0

Требуется ли местное заявление? Кроме того, не могли бы вы объяснить, почему нам нужны оба оператора% let? Почему бы не '% let tmp_date =% sysfunc (intnx (month, & iStart_date, 0, begin))' работать, заменяя 0 на & i и имея i = x (количество месяцев)? – DukeLuke

+0

Код будет работать без оператора '% local', но это оставит его открытым для макросъемки. Лучше всего всегда определять любые переменные, локальные для этого макроса, с помощью оператора '% local'. В этом конкретном случае технически требуется только вторая '% let'. У меня есть оба из них, потому что он был забит во мне как правильная структура для цикла while, когда я вернулся в школу (инициализируйте значение снаружи, а затем повторите его в цикле). И да, вы можете воссоздать цикл '% do'; Существует много альтернативных способов кодирования, сделайте то, что лучше всего подходит для вас. =) –

+1

@DukeLuke. Если вы хотите больше узнать о макрообрисовке, документацию можно найти здесь: http://support.sas.com/documentation /cdl/en/mcrolref/67912/HTML/default/viewer.htm#n10i4tmalsyhgxn1hj4ud13ff074.htm –

2

Вот один из способов сделать такой цикл:

%macro month_loop(MTH_FROM, MTH_TO); 
    %local T_MTH_FROM T_MTH_TO MTH_DIFF CUR_MTH MTH_OFFSET; 
    %let T_MTH_FROM = %sysfunc(inputn(&MTH_FROM,yymmn.)); 
    %let T_MTH_TO = %sysfunc(inputn(&MTH_TO,yymmn.)); 
    %let MTH_DIFF = %sysfunc(intck(month,&T_MTH_FROM,&T_MTH_TO)); 

    %do MTH_OFFSET = 0 %to &MTH_DIFF; 
    %let CUR_MTH = %sysfunc(intnx(month,&T_MTH_FROM,&MTH_OFFSET), yymmn4.); 
    %put CUR_MTH = &CUR_MTH; 
    %end; 
%mend; 

%month_loop(1001,1607); 
0

Это немного трудно следовать вашей логике, но это выглядит, как вы просто хотите сделать:

data final; 
    set appd.file work01-work03 ; 
run; 
+0

Если SAS разрешало использовать совпадение '-' для наборов данных вместо простых переменных, это сработало бы. У совпадения '-' будут проблемы, потому что между месячными наборами данных 1012 и 1101 будет разрыв, а' -' не будет поддерживать пробелы. –

Смежные вопросы