Как найти максимальное значение переменной для каждого уникального наблюдения в наборе «сложенных» данных - PullRequest
6 голосов
/ 14 июля 2010

Извините за смелый заголовок.

Мой набор данных выглядит в основном так:

ID   X
18   1
18   1
18   2
18   1
18   2
369  2
369  3
369  3
361  1

я хочу найти максимальное значение x для каждого идентификатора. В этом наборе данных это будет 2 для ID = 18 и 3 для ID = 361.

Любая обратная связь будет принята с благодарностью.

Ответы [ 7 ]

8 голосов
/ 16 июля 2010

Proc Означает использование оператора класса (поэтому вам не нужно сортировать) и запрос максимальной статистики, вероятно, самый простой подход (не проверенный):

data sample; 
    input id x; 
datalines; 
18  1 
18  1 
18  2 
18  1 
18  2 
369 2 
369 3 
369 3 
361 1 
; 
run; 


proc means data=sample noprint max nway missing; 
   class id;
   var x;
   output out=sample_max (drop=_type_ _freq_) max=;
run; 

Более подробную информацию о средствах Proc можно найти в онлайн-документации SAS (http://support.sas.com/onlinedoc/913/docMainpage.jsp).

).
3 голосов
/ 15 июля 2010

Я не совсем понимаю ваш пример.Я не могу себе представить, что входной набор данных действительно имеет все значения в одном наблюдении.Вместо этого вы имеете в виду нечто подобное?

data sample;
    input myid myvalue;
datalines;
18  1
18  1
18  2
18  1
18  2
369 2
369 3
369 3
361 1
;

proc sort data=sample;
    by myid myvalue;
run;

data result;
    set sample;
    by myid;

    if last.myid then output;
run;

proc print data=result;
run;

Это даст вам такой результат:

Obs    myid    myvalue

 1       18       2   
 2      361       1   
 3      369       3   
2 голосов
/ 26 июля 2014

Если вы хотите сохранить все записи и максимальное значение X по идентификатору, я бы использовал либо подход PROC MEANS с последующим оператором слияния, либо вы можете сначала отсортировать данные по Id и DESCENDING X, а затем использовать оператор RETAIN для создания значения max_value непосредственно в шаге данных:

PROC SORT DATA=A; BY ID DESCENDING X; RUN;

DATA B; SET A;
BY ID;
RETAIN  X_MAX;
IF FIRST.ID  THEN   X_MAX = X;
ELSE                X_MAX = X_MAX;
RUN;
1 голос
/ 02 октября 2015

Несколько более изощренных опций, которые могут быть интересны всем, кому нужно сделать это с действительно большим набором данных, где производительность более важна:

  1. Если ваш набор данныхуже отсортированы по идентификатору, но не по X внутри каждого идентификатора, вы все равно можете сделать это за один шаг данных без какой-либо сортировки, используя сохраненный максимум в каждой группе.В качестве альтернативы вы можете использовать средства proc (согласно верхнему ответу), но с оператором by вместо оператора class - это уменьшает использование памяти.
data sample; 
    input id x; 
datalines; 
18  1 
18  1 
18  2 
18  1 
18  2 
369 2 
369 3 
369 3 
361 1 
; 
run; 

data want;
  do until(last.ID);
    set sample;
    by ID;
    xmax = max(x, xmax);
  end;
  x = xmax;
  drop xmax;
run;
Даже если ваш набор данных не отсортирован по идентификатору, вы все равно можете сделать это за один шаг данных, не сортируя его, используя хеш-объект для отслеживания максимального значения x, которое вы нашли для каждого идентификатора на ходу.вместе.Это будет немного быстрее, чем proc means, и, как правило, будет использовать меньше памяти, так как proc означает, что выполняет различные вычисления в фоновом режиме, которые не нужны в выходном наборе данных.
data _null_;
  set sample end = eof;
  if _n_ = 1 then do;
    call missing(xmax);
    declare hash h(ordered:'a');
    rc = h.definekey('ID');
    rc = h.definedata('ID','xmax');
    rc = h.definedone();
  end;
  rc = h.find();
  if rc = 0 then do;
    if x > xmax then do;
        xmax = x;
        rc = h.replace();
    end;
  end;
  else do;
    xmax = x;
    rc = h.add();
  end;
  if eof then rc = h.output(dataset:'want2');
run;

В этом примерена моем ПК хэш-подход использовал столько памяти:

   memory              966.15k
   OS Memory           27292.00k

против.это много для эквивалентной сводки процедур:

   memory              8706.90k
   OS Memory           35760.00k

Неплохая экономия, если она действительно нужна для увеличения!

1 голос
/ 18 сентября 2013

Вы можете попробовать это:

PROC SQL;
CREATE TABLE CHCK AS SELECT MYID, MAX(MYVALUE) FROM SAMPLE
GROUP BY 1;
QUIT;
0 голосов
/ 03 января 2014

Я бы просто отсортировал по x и id, поместив самое высокое значение для каждого идентификатора вверху.NODUPKEY удаляет каждый дубликат ниже.

proc sort data=yourstacked_data out=yourstacked_data_sorted;
by DECENDING x id;
run;

proc sort data=yourstacked_data NODUPKEY out=top_value_only;
by id;
run;
0 голосов
/ 15 июля 2010

Используйте соответствующий proc с оператором by.Например,

data sample;
    input myid myvalue;
datalines;
18  1
18  1
18  2
18  1
18  2
369 2
369 3
369 3
361 1
;
run;

proc sort data=sample;
  by myid;
run;

proc means data=sample;
   var myvalue;
   by myid;
run;
...