Сравнение значений между строками, а затем удаление повторяющихся значений в SAS

#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;