У меня есть такой набор данных (только с большим количеством учетных записей и, следовательно, наблюдений) * Переменная 1001 *
data dataset;
input account_id month date9. default_flag;
format month date9.;
datalines;
22 31JAN2004 0
22 29FEB2004 0
22 31MAR2004 0
22 30APR2004 0
22 31MAY2004 0
22 30JUN2004 0
22 31JUL2004 0
22 31AUG2004 0
22 30SEP2004 0
22 31OCT2004 0
22 30NOV2004 0
22 31DEC2004 0
22 31JAN2005 0
22 28FEB2005 0
22 31MAR2005 0
22 30APR2005 0
22 31MAY2005 1
;
run;
default_flag
указывает, является ли учетная запись по умолчанию (default_flag=1
) или нет (default_flag=0
).
Я хочу создать флаговую переменную по умолчанию для X-месяцев defXMON_flag
, которая равна 1, если учетная запись вводит значение по умолчанию в следующие X месяцев, и существует как минимум X месяцев наблюдений. Если учетная запись вводит значение по умолчанию, но наблюдений меньше, чем X месяцев, тогда переменная будет равна 3.
Мне нужно создать несколько таких переменных для нескольких разных X. Допустим, я хочу создать две такие переменные - одна для X = 12 месяцев (def12MON_flag
) и одна для X = 15 месяцев (def15MON_flag
).
Я придумал следующий код, который дает нужные мне результаты:
proc sql noprint;
create table defaults as
select a.account_id, a.month, a.default_flag,
sum(b.default_flag) as nr_defaults_12 format = comma17.,
count(distinct b.month) as nr_months_12,
case when a.default_flag = 0
and coalesce(calculated nr_defaults_12, 0) eq 0
and coalesce(calculated nr_months_12, 0) = 12 then 0
when a.default_flag = 0
and coalesce(calculated nr_defaults_12, 0) ne 0
and coalesce(calculated nr_months_12, 0) = 12 then 1
when a.default_flag = 0
and coalesce(calculated nr_defaults_12, 0) eq 0
and coalesce(calculated nr_months_12, 0) ne 12 then 2
when a.default_flag = 0
and coalesce(calculated nr_defaults_12, 0) ne 0
and coalesce(calculated nr_months_12, 0) ne 12 then 3
else .
end as def12MON_flag,
sum(c.default_flag) as nr_defaults_15 format = comma17.,
count(distinct c.month) as nr_months_15,
case when a.default_flag = 0
and coalesce(calculated nr_defaults_15, 0) eq 0
and coalesce(calculated nr_months_15, 0) = 15 then 0
when a.default_flag = 0
and coalesce(calculated nr_defaults_15, 0) ne 0
and coalesce(calculated nr_months_15, 0) = 15 then 1
when a.default_flag = 0
and coalesce(calculated nr_defaults_15, 0) eq 0
and coalesce(calculated nr_months_15, 0) ne 15 then 2
when a.default_flag = 0
and coalesce(calculated nr_defaults_15, 0) ne 0
and coalesce(calculated nr_months_15, 0) ne 15 then 3
else .
end as def15MON_flag
from ( select account_id, month, default_flag from dataset where default_flag = 0) a
left outer join ( select account_id, default_flag, month from dataset ) b
on 1=1
and a.account_id = b.account_id
and b.month between intnx('month', a.month, 1, 'end')
and intnx('month', a.month, 12, 'end')
left outer join ( select account_id, default_flag, month from dataset ) c
on 1=1
and a.account_id = c.account_id
and c.month between intnx('month', a.month, 1, 'end')
and intnx('month', a.month, 15, 'end')
group by a.account_id, a.month, a.default_flag
order by a.account_id, a.month;
quit;
run;
Это мой конечный результат - не важная часть, важная часть - создание таблицы defaults
, которую мне нужно оптимизировать.
PROC SQL;
CREATE TABLE RESULT AS
SELECT T.*, S.DEF12MON_FLAG, S.DEF15MON_FLAG
FROM DATASET T
LEFT JOIN DEFAULTS S
ON T.ACCOUNT_ID = S.ACCOUNT_ID
AND T.MONTH = S.MONTH
ORDER BY ACCOUNT_ID, MONTH
;
Однако проблема с этим кодом является то, что он использует два левых соединения огромного набора данных при создании таблицы defaults
(в действительности, мне нужно было бы использовать еще больше левых объединений для большего количества defXMON_flag
переменных), и его невозможно запустить из-за размера эти наборы данных. Можно ли получить тот же результат без тех левых соединений? Можете ли вы предложить более эффективный способ вычисления def12MON_flag
и def15MON_flag
с тем же результатом, что и этот код?