#if-statement #sas #sas-macro
Вопрос:
Это моя логика мышления для моих утверждений if в SAS. Он не работает, потому что мне сказали, что я использую его неправильно. Может ли кто-нибудь оказать помощь, пожалуйста?
ОШИБКА 180-322: Оператор неверен или используется не в правильном порядке.
data tmp_final_tab;
merge data.final_alerts_ramts(in=a) data.final_alerts_repamts(in=b) data.final_alerts_passthru(in=c)
data.final_alerts_wires(in=d) data.final_alerts_low_volume(in=e) data.final_alerts_bhvr(in=f);
by clnt_no;
if a;
if pamt_activity_cr >= amp;rnd_pct_atl then atl_inda1 = 1; else atl_inda1 = 0;
if pamt_activity_dr >= amp;rnd_pct_atl then atl_inda2 = 1; else atl_inda2 = 0;
if b;
if pamt_activity_cr >= amp;rnd_pct_atl then atl_indb1 = 1; else atl_indb1 = 0;
if pamt_activity_dr >= amp;rnd_pct_atl then atl_indb2 = 1; else atl_indb2 = 0;
if c;
if (ptam/total_Amount) * 100 >= amp;pt_pct_atl then atl_indc = 1; else atl_indc = 0;
if d;
if tot_amt_wire >= amp;hrc_wire_amt_atl then atl_indd = 1; else atl_indd1 = 0;
if tot_in_amt >= amp;wire_in_cnt_amt_atl then atl_indd2 = 1; else atl_indd2 = 0;
if tot_out_amt >= amp;wire_out_cnt_amt_atl then atl_indd3 = 1; else atl indd3 = 0;
if e;
if tot_amt_lv >= amp;lv_amt_atl then atl_ind = 1; else atl_ind = 0;
if f;
if tot_amt_bhvr >= amp;bhvr_w_hist_atl then atl_ind = 1; else atl_ind = 0;
if a or b or c or d or e or f
if (atl_inda atl_indb atl_indc atl_indd atl_inde atl_indf > 0) then btl_ind = 0; else btl_ind = 1;
run;
Комментарии:
1. Большинство операторов IF с отступом на том же уровне, что и оператор BY, являются ПОДМНОЖЕСТВАМИ операторов IF, а не операторов IF/THEN. В последнем отсутствует конечная точка с запятой. Из-за операторов подмножества IF ваши результаты будут включать только значения CLNT_NO, которые отображаются во всех 6 входных наборах данных. Вы намерены исключить значения CLNT_NO, отсутствующие в одном или нескольких входных наборах данных?
Ответ №1:
if
Заявление в SAS всегда имеет следующую форму (без <>
):
if <boolean logic> then <code>;
Если оцениваемой логике необходимо выполнить более одной задачи, она следует этой форме:
if <boolean logic> then do;
<code>;
<code>;
<code>;
...
end;
Похоже, что весь ваш код создает двоичные переменные. Этот ярлык программирования в SAS создаст для вас двоичные переменные 1/0:
binary_var = (<boolean logic>);
Если логика верна, binary_var
равна 1. В противном случае она равна 0.
Правильная форма вашего кода приведена ниже с более чистой формой ваших новых двоичных переменных.
data tmp_final_tab;
merge data.final_alerts_ramts (in=a)
data.final_alerts_repamts (in=b)
data.final_alerts_passthru (in=c)
data.final_alerts_wires (in=d)
data.final_alerts_low_volume(in=e)
data.final_alerts_bhvr (in=f)
;
by clnt_no;
if a then do;
atl_inda1 = (pamt_activity_cr >= amp;rnd_pct_atl);
atl_inda2 = (pamt_activity_dr >= amp;rnd_pct_atl);
end;
if b then do;
atl_indb1 = (pamt_activity_cr >= amp;rnd_pct_atl);
atl_indb2 = (pamt_activity_dr >= amp;rnd_pct_atl);
end;
if c then atl_indc = ( (ptam/total_Amount) * 100 >= amp;pt_pct_atl);
if d then do;
atl_indd = (tot_amt_wire >= amp;hrc_wire_amt_atl);
atl_indd2 = (tot_in_amt >= amp;wire_in_cnt_amt_atl);
atl_indd3 = (tot_out_amt >= amp;wire_out_cnt_amt_atl);
end;
atl_ind = ( (e AND tot_amt_lv >= amp;lv_amt_atl) OR (f AND tot_amt_bhvr >= amp;bhvr_w_hist_atl) );
btl_ind = (sum(atl_inda, atl_indb, atl_indc, atl_indd, atl_inde, atl_indf) > 0);
run;
Технически вам здесь даже не нужны if
заявления. Вы можете включить in
логику набора данных в каждую двоичную переменную (например binary_var = (a AND <logic>);
. Если пропущенные значения в этой операции не требуются, вы можете полностью удалить эти if
операторы.
Ответ №2:
if a;
является оператором подмножества if и очень часто используется при слияниях, подобных приведенным выше, хотя, вероятно, вы не это имели в виду. Подстановка if означает, что шаг данных должен прекратить выполнение и перейти к следующей строке, если if
условие не выполняется.
В случае вышесказанного, if a;
true
если текущая объединенная строка включает некоторые данные из первого набора данных (который имеет in=a
в своих параметрах набора данных).
Хотя нет смысла разбрасывать их вокруг , как вы это сделали, — это наводит на мысль, что вы действительно имеете в виду if it comes from a then do these things
, что нет if it doesn't come from a then drop it
.
Кроме того, со всеми шестью ( if a; if b; if c;...
) будут сохранены только строки, которые имеют некоторое значение во всех шести входных наборах inner join
данных — и тогда ваш последний раздел не имеет смысла (тот, с or
которым ). Но было бы разумнее сделать это:
if a and b and c and d and e and f;
Еще одно примечание: есть select
утверждение, которое иногда может быть полезно в такого рода организации. Однако это было бы полезно только в том случае, если вы ожидали, что только одно из условий будет истинным, или же хотели, чтобы выполнялось только одно из них, независимо от того, сколько из них было истинным — оно выполняет первое, которое является истинным, а затем уходит.