Любой умный способ реорганизовать набор данных (возможно, с задержкой и выводом)? - PullRequest
1 голос
/ 06 марта 2020

Может кто-нибудь придумать хорошую идею для достижения следующих целей в SAS?

У нас есть

data test;
input ID $ Score Month_visit;
datalines;
Pat1 10 0
Pat1 9 3
Pat1 3 6
Pat1 7 8
;

, и я хочу, чтобы эти тестовые данные были преобразованы в

data final;
input ID $ Score Month;
datalines;
Pat1 10 0
Pat1 10 1
Pat1 10 2
Pat1 9 3
Pat1 9 4
Pat1 9 5
Pat1 3 6
Pat1 7 7
Pat1 7 8
;

так что в основном счет должен быть напечатан так же часто, как разница (Month_visit - "change of Month_visit"), а затем просто пересчитан.

У меня такое ощущение, что это можно сделать с помощью функции lag() - и output statement но пока не смог сделать это правильно. Любые идеи?

Обновление:

На самом деле оптимальным было бы также охватить процесс для различных ID с в наборе данных:

data test;
input ID $ Score Month_visit;
datalines;
Pat1 10 0
Pat1 9 3
Pat1 3 6
Pat1 7 8
Pat2 6 1
Pat2 2 3
Pat2 3 6
Pat2 7 8
;

Решение для обновления:

Если мы придерживаемся решения, предоставленного @draycut, мы можем просто ввести by statement в шаг данных, мы получим:

data want (drop=Month_visit:);
    merge test
          test (firstobs=2 keep=Month_visit rename=Month_visit=Month_visit_);
run;

data final;
set want;
by ID;
    if (last.ID NE 1) then do Month = Month_visit to Month_visit_-1;
        output;
    end;
    else do;
        Month = Month_visit;
        output;
    end;
run;

Ответы [ 3 ]

2 голосов
/ 06 марта 2020

Вы не реорганизуете данные, вы вменяете пропущенные значения, перенося текущее значение через монотонного c стража прогрессии в следующем ряду.

Значения из следующей строки считаются отведениями , а умными повторным использованием набора данных, начиная со второй строки, в Слияние 1: 1 может обеспечить это.

Пример

Ваши значения month_visit увеличиваются, но в более широкой задаче, предположим, что были случаи уменьшения или отсутствия значений и несколько ID групп.

data have;
input ID $ Score Month_visit;
datalines;
Pat1 10 0
Pat1 9 3
Pat1 3 6
Pat1 7 8
Pat1 4 4
Pat1 11 0
Pat2 11 0
Pat2 4 4
Pat2 7 . 
Pat2 3 6
Pat2 9 3
Pat2 10 .
;
data want;
  /* 1:1 merge, NO BY STATEMENT */
  merge
    have
    have (firstobs=2 keep=id month_visit rename=(month_visit=lead_month id=lead_id))
  ;

  array step[-1:1] _temporary_ (-1,1,1); /* clever mapping for SIGN() result */

  if lead_id = id and not missing(lead_month) and not missing(month_visit) then
  do month_visit = month_visit 
       to lead_month - step[sign(lead_month - month_visit)]
       by              step[sign(lead_month - month_visit)]
  ;
    output;
  end;
  else 
    output;
run;

Также см. Аналогичный вопрос Замена первой строки значениями во второй строке , где значение опережения используется для вменения.

2 голосов
/ 06 марта 2020

Вы можете рассмотреть метод, который не полагается на посещения, являющиеся целыми числами.

data test;
   input ID $ Score Visit :$10.;
   datalines;
Pat1 10 Baseline
Pat1 9  V-3
Pat1 3  V-6
Pat1 7  V-EOT
Pat2 6  V-1
Pat2 2  V-3
Pat2 3  V-6
Pat2 7  V-EOT
;;;;
proc print;
   run;
data schedule;
   input Visit :$10.;
   cards;
Baseline
V-1
V-2
V-3
V-4
V-5
V-6
V-EOT
;;;;
   run;
proc summary data=test classdata=schedule nway ORDER=DATA;
   by id;
   class visit;
   output out=want0(drop=_:) idgroup(out(score)=);
   run;
proc print;
   run;
data want;
   update want0(obs=0) want0;
   by id;
   output;
   run;
proc print;
   run;

enter image description here

2 голосов
/ 06 марта 2020

Как насчет этого?

Кроме того, почему счет = 7 в ваших 8-х матчах в финале? Разве это не должно быть 3?

data test;
input ID $ Score Month_visit;
datalines;
Pat1 10 0
Pat1 9 3
Pat1 3 6
Pat1 7 8
;

data want (drop=Month_visit:);
    merge test
          test (firstobs=2 keep=Month_visit rename=Month_visit=Month_visit_);
    if Month_visit_ ne . then do Month = Month_visit to Month_visit_-1;
        output;
    end;
    else do;
        Month = Month_visit;
        output;
    end;
run;
...