если _N_ = 1, условие возвращает истину, даже если установленный набор данных пуст (ноль наблюдений) в SAS - PullRequest
5 голосов
/ 11 октября 2011

Сомнение в SAS:

    data new;
        set _NULL_;
    run;

   data _NULL_;
        set new;
        if _N_ = 0 then call execute ("%put empty dataset;");
        if _N_ = 1 then call execute ("%put non-empty dataset;");
   run;

Приведенный выше фрагмент кода в моем понимании должен печатать только первый комментарий, то есть пустой набор данных.По какой-то причине он возвращает истину для второго условия if и печатает также непустой набор данных.

Пожалуйста, дайте мне знать, где я ошибаюсь?

1 Ответ

10 голосов
/ 11 октября 2011

Хорошо, вот что я думаю, что происходит.Первая проблема заключается в том, что ваши вызовы макросов заключены в двойные кавычки и поэтому обрабатываются препроцессором еще до того, как SAS даже начал обрабатывать шаг данных (выполняется независимо от того, является ли условие if истинным или нет).Вы должны поместить аргумент для выполнения в одинарные кавычки, а не в двойные кавычки, чтобы предотвратить его преждевременное выполнение макропроцессором.

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

В-третьих, _N_ инициализируется в 1, а не в 0, и увеличивается оттуда на границе шага данных, так что условие _N_ = 0 всегда будет ложным.

Альтернативный способ сделать это - использовать параметр nobs =, чтобы установить следующее:

data _NULL_;
  if 0 then set new nobs=num_obs;
  if num_obs = 0 then call execute ('%put empty dataset;');
  if num_obs > 0 then call execute ('%put non-empty dataset;');
stop;
run;

if 0 then - фиктивное условие, используемое для принудительного выполнения кода шага данных;если использовался пустой оператор set, выполнение не продолжалось бы после строки набора, если набор данных "new" был пуст.

Лучшим вариантом может быть использование макросов для открытия набора данных и чтения атрибута ANY:

%let dsid = %sysfunc (open(dataset_name));
%let anyobs = %sysfunc (attrn(&dsid,ANY));
%let dsid = %sysfunc (close(&dsid));

Макропеременная &anyobs будет равна 1, если dataset_name содержит хотя бы одно наблюдение (строку) и хотя бы одну переменную (столбец), 0, если она не содержит наблюдений, но хотя бы одну переменную, и -1, если он не содержит наблюдений и переменных.

...