Как подавить ноту бесконечного цикла при использовании IF 0 THEN SET

Чтобы «скопировать» структуру PDV набора данных, рекомендуется "ссылаться набор данных во время компиляции», используя

if 0 then set <data-set>

Например,

data toBeCopied;
    length var1 $ 4. var2 $ 4. ;
    input var1 $ var2 $;

    datalines;
    this  is
    just  some
    fake  data 
    ;
run;

data copyPDV;
    if 0 then set toBeCopied;

    do var1 = 'cutoff' ;
        do var2 =  'words';
            output;
        end;
    end;    
run;

Однако при выполнении этого в журнале появляется следующее ПРИМЕЧАНИЕ:

ПРИМЕЧАНИЕ. ШАГ ДАННЫХ остановлен из-за зацикливания.

Это связано с тем, что шаг данных никогда не достигает маркера EOF и застревает в бесконечном цикле, как описано в Зацикливание набора данных. (Оказывается, шаг ДАННЫЕ распознает это и завершает цикл, следовательно, ПРИМЕЧАНИЕ в журнале).

Похоже, что использование оператора if 0 then set <data-set> является давней практикой, восходящей к 1987 году. Хотя мне это кажется хакерским, я не могу придумать другого способа получить тот же результат (т.е. скопировать структуру PDV), кроме ручного повторная формулировка требований к атрибутам. Мне также кажется плохой формой позволять ОШИБКАМ, ПРЕДУПРЕЖДЕНИЯМ и ПРИМЕЧАНИЯМ, которые подразумевают непреднамеренное поведение программы, оставаться в журнале.

Есть ли способ подавить это примечание или вообще лучший метод для достижения того же результата (т. е. копирования структуры PDV набора данных)?

Если вы включите оператор stop;, как в

if 0 then do;
        set toBeCopied;
        stop;
    end;

ПРИМЕЧАНИЕ все еще сохраняется.

Попытка ограничить SET одним наблюдением также не дает результата:

if 0 then set toBeCopied (obs=1);


person Lorem Ipsum    schedule 21.09.2016    source источник
comment
На самом деле проблема не в том, как вы определяете свои переменные, а в том, как вы определяете свои наблюдения.   -  person Tom    schedule 21.09.2016
comment
Вы понимаете, что делает if 0? Это может быть частью вашей проблемы здесь.   -  person Joe    schedule 21.09.2016
comment
@ Том Не могли бы вы уточнить? Если я сделаю что-то вроде data copyPDV_v2; if 0 then set toBeCopied; input var1 $ var2 $; datalines; cutoff words cutoff words ; run;, я больше не получаю ошибку, но это, похоже, противоречит цели использования if 0 then set (чтобы избежать ручного копирования переменных/атрибутов)   -  person Lorem Ipsum    schedule 21.09.2016
comment
Смотрите ответ ниже для более подробной информации.   -  person Tom    schedule 21.09.2016


Ответы (3)


Обычно SAS завершает шаг данных в тот момент, когда вы читаете входные данные. Либо необработанные данные, либо наборы данных SAS. Например, этот шаг данных остановится, когда он выполнит оператор SET в 6-й раз и обнаружит, что больше нет наблюдений для чтения.

data want;
  put _n_=;
  set sashelp.class(obs=5);
run;

Чтобы предотвратить циклы, SAS проверяет, читали ли вы какие-либо наблюдения в этой итерации шага данных. Он достаточно умен, чтобы не предупреждать вас, если вы не читаете какие-либо наборы данных. Таким образом, эта программа не получает предупреждения.

data want ;
  do age=10 to 15;
    output;
  end;
run;

Но, добавив этот оператор SET, вы запустили проверку. Вы можете предотвратить появление предупреждения, если у вас есть набор данных, который вы фактически читаете, чтобы он останавливался, когда считывается за конец фактических входных данных.

data want;
  if 0 then set sashelp.class ;
  set my_class;
run;

Или файл, который вы читаете.

data want ;
  if 0 then set sashelp.class ;
  infile 'my_class.csv' dsd firstobs=2 truncover ;
  input (_all_) (:) ;
run;

В противном случае добавьте оператор STOP, чтобы вручную завершить шаг данных.

data want ;
  if 0 then set sashelp.class;
  do age=10 to 15;
   do sex='M','F';
    output;
   end;
  end;
  stop;
run;
person Tom    schedule 21.09.2016
comment
Хотя это и не решение, альтернативой является вставка put 'NOTE: The following DATA STEP stop is intentional' или чего-то еще, что позволит читателю понять, что это не ошибка. Пока оператор включает ПРИМЕЧАНИЕ:, строка в журнале будет окрашена соответствующим образом. - person Lorem Ipsum; 22.09.2016

stop не должно быть в ветке if 0. Эта ветвь никогда не выполняется. stop необходимо выполнить и выполнить в том месте, где вы хотите остановить выполнение.

data copyPDV;
    if 0 then set toBeCopied;

    do var1 = 'cutoff' ;
        do var2 =  'words';
            output;
        end;
    end;    
    stop;
run;
person Joe    schedule 21.09.2016
comment
О! Конечно, это имеет смысл. Вся концепция if 0 then set основана на том факте, что if 0 всегда ложно и поэтому никогда не выполняется. - person Lorem Ipsum; 21.09.2016
comment
Вы знаете другой способ реализовать это? Поскольку if 0 then set довольно непрозрачно, я инстинктивно добавляю его в макрос с информативным именем, таким как %CopyPDVStructure(<data-set>);, чтобы логика была более очевидной, и тем, кто не знаком с ней, не нужно было сбиваться с толку. Этот подход не будет работать, если операторы if и stop; находятся в разных ветвях. - person Lorem Ipsum; 21.09.2016
comment
Я не думаю, что назвал бы if 0 then set непрозрачным, довольно просто понять, что он со мной делает. Но это зависит от вас, я думаю. Если вы хотите иметь возможность произвольно вставлять данные на шаге данных, я думаю, что вашим единственным вариантом будет довольно сложный макрос, который использует DOSUBL и таблицы словаря для его построения; решения, о которых упоминает Шэнлин Чен, работают нормально, если вы согласны с тем, что это автономный шаг данных или блок SQL. - person Joe; 21.09.2016
comment
Я согласен с Джо, if 0 then set используется достаточно, чтобы быть знакомым программистам SAS. Тем не менее, если вы действительно хотите скрыть это в макросе, и вы знаете, что пользователям макросов никогда не понадобятся две итерации цикла шага данных, я полагаю, что вы могли бы сделать свой макрос: if 0 then set &data; if _n_=2 then stop; Но это было бы опасно для меня, потому что подход if 0 then set часто используется в настройках, где пользователь хочет (нуждается) несколько итераций пошагового цикла данных. Безопаснее позволить им жить с ЗАМЕЧАНИЕМ: или, что еще лучше, запрограммировать их собственный СТОП. - person Quentin; 21.09.2016
comment
На самом деле, если подумать, если вы используете set sashelp.class(obs=0); из ответа Шэнлина Чена, это должно нормально работать в макросе, не так ли? - person Joe; 21.09.2016
comment
@joe не думаю, что это будет работать так, как хочет ОП, когда они записывают записи в выходной набор данных. Как только set sashelp.class(obs=0); выполнится, я думаю, что это завершит шаг данных. - person Quentin; 22.09.2016
comment
@Quentin Это было поведение, которое я испытал с set sashelp.class (obs=0);. - person Lorem Ipsum; 22.09.2016
comment
@Quentin Квентин А, хорошая мысль - это работает только на отдельном шаге данных. - person Joe; 22.09.2016

Не подавлять эту заметку в вашей ситуации. Это способ получить структуру набора данных.

data class;
   set sashelp.class(obs=0);
run;

or

proc sql;
   create table class1 like sashelp.class;
quit;
person Shenglin Chen    schedule 21.09.2016