#sas #sas-macro
#САС #sas-макрос
Вопрос:
У меня есть набор данных , в котором есть определенные переменные , теперь мне нужно сравнить эти переменные между строками, чтобы найти дубликат, но у него мало дополнительных запросов .
- если для одного и того же acct_num и test_id
— если final_amt совпадает с final_amt из следующей строки, а final_amt_added совпадает с final_amt_added из следующей строки, мы должны рассматривать их как дубликаты и удалять только тот случай, когда значение tran_date пустое.
— Также , если мы удаляем дублирующуюся строку с пустой датой tran_date, данные actual_amt из этой строки должны быть сохранены как новая переменная act_amt_extra в восстановленной строке.
Я перепробовал несколько сценариев с использованием задержки и сохранения, но данные просто поступают неправильно, любая помощь будет признательна.
DATA work.sample; INPUT acct_num test_id tran_date:anydtdte. actual_amt final_amt final_amt_added ; format tran_date date9.; DATALINES; 55203610 2542 12-jan-20 30 45 45 16124130 8062 . 56 78 78 16124130 8062 14-dec-19 8 78 78 80479512 2062 19-mar-19 32 32 32 70321918 2062 20-dec-19 1 93 54 17312410 6712 . 45 90 90 17312410 6712 15-jun-18 0 90 90 74623123 2092 17-aug-18 34 87 87 24245321 2082 22-jan-17 22 56 67 ; run;
данные, которые мне нужны
data want; input acct_num test_id tran_date:anydtdte. actual_amt final_amt final_amt_added act_amt_extra; format tran_date date9.; DATALINES; 55203610 2542 12-jan-20 30 45 45 16124130 8062 14-dec-19 8 78 78 56 80479512 2062 19-mar-19 32 32 32 70321918 2062 20-dec-19 1 93 54 17312410 6712 15-jun-18 0 90 90 45 74623123 2092 17-aug-18 34 87 87 24245321 2082 22-jan-17 22 56 67 ; run;
Ответ №1:
Возможно, это не самый элегантный способ обработки, но он будет работать до тех пор, пока у вас есть только один дубликат, как показано в вашем примере.
Данные, которые нас больше всего интересуют, — это когда дата не пропущена. Во-первых, отсортируйте свои данные по acct_num test_id
убыванию tran_date
:
proc sort data=sample; by acct_num test_id descending tran_date; run;
Это гарантирует, что данные, которые нас интересуют, являются первыми:
acct_num test_id tran_date actual_amt final_amt final_amt_added 16124130 8062 14DEC2019 8 78 78 16124130 8062 . 56 78 78
Мы хотим вывести только последнюю комбинацию acct_num test_id
. Когда есть дубликаты, мы хотим выдвинуть следующие значения:
tran_date
actual_amt
Обратите внимание, что когда есть дубликаты и мы хотим перенести значения вперед, мы знаем следующее:
last.test_id
это правдаfirst.test_id
является ложнымtran_date
отсутствуетfinal_amt
соответствует значению предыдущей строкиfinal_amt_added
соответствует значению предыдущей строки
Когда это произойдет, мы запустим нашу логику. В противном случае мы оставим строку как есть и выведем результат.
data want; set sample; by acct_num test_id descending tran_date; /* Store prior values */ lag_actual_amt = lag(actual_amt); lag_final_amt_added = lag(final_amt_added); lag_final_amt = lag(final_amt); lag_tran_date = lag(tran_date); /* Bring forward data if conditions are met */ if( missing(tran_date) AND last.test_id AND NOT first.test_id AND final_amt = lag_final_amt AND final_amt_added = lag_final_amt_added ) then do; act_amt_extra = actual_amt; /* Bring forward the prior values */ tran_date = lag_tran_date; actual_amt = lag_actual_amt; end; /* Only output for the last combination of acct_num, test_id */ if(last.test_id); drop lag:; run;
Комментарии:
1. Спасибо, что это сработало.
Ответ №2:
Вот довольно элегантный способ получить то, что вы хотите:
proc sort data=sample; by acct_num tran_date; run; data want; set sample; by acct_num tran_date; act_amt_extra = lag(actual_amt); if first.acct_num then act_amt_extra = .; if tran_date = . then delete; run;