Суммарные наблюдения SAS не в группе, по нескольким группам - PullRequest
0 голосов
/ 05 марта 2020

Этот пост следует за этим: Наблюдения суммы SAS не в группе, по группе К сожалению, мой минимальный пример был слишком минимальным, но я не смог использовать его в своих данных.

Вот полный пример, который у меня есть:

data have;
   input group1 group2 group3 $ value;
   datalines;
1 A X 2
1 A X 4
1 A Y 1
1 A Y 3
1 B Z 2
1 B Z 1
1 C Y 1
1 C Y 6
1 C Z 7
2 A Z 3
2 A Z 9
2 A Y 2
2 B X 8
2 B X 5
2 B X 5
2 B Z 7
2 C Y 2
2 C X 1
;
run;

Для каждой группы я хочу новую переменную «сумма» с суммой всех значений в столбце для того же суб groups (group1 и group2), за исключением группы (group3), в которой находится наблюдение.

data want;
   input group1 group2 group3 $ value $ sum;
   datalines;
1 A X 2 8
1 A X 4 6
1 A Y 1 9
1 A Y 3 7
1 B Z 2 1
1 B Z 1 2
1 C Y 1 13
1 C Y 6 8
1 C Z 7 7
2 A Z 3 11
2 A Z 9 5
2 A Y 2 12
2 B X 8 17
2 B X 5 20
2 B X 5 20
2 B Z 7 18
2 C Y 2 1
2 C X 1 2
;
run;

Моя цель - использовать либо шаги данных, либо pro c sql (делать это примерно на 30 миллионах Наблюдения и pro c означают и такие в SAS, кажется медленнее, чем в предыдущих аналогичных вычислениях.

Моя проблема с решениями, представленными в связанном посте, заключается в том, что используется общее значение столбца, и я не не знаю, как это изменить, используя итоги в подгруппе. Любая идея, пожалуйста?

1 Ответ

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

Решение SQL объединит все данные в агрегирующий выбор:

proc sql;
  create table want as 
  select have.group1, have.group2, have.group3, have.value
    , aggregate.sum - value as sum 
  from 
    have
  join 
    (select group1, group2, sum(value) as sum
     from have
     group by group1, group2
    ) aggregate
  on
    aggregate.group1 = have.group1
  & aggregate.group2 = have.group2
;

SQL может быть медленнее, чем решение ha sh, но код SQL понимают больше людей, чем те, которые понимают шаг SAS DATA с использованием хэшей (который может быть быстрее SQL.)


data want2;
  if 0 then set have; * prep pdv;

  declare hash sums (suminc:'value');
  sums.defineKey('group1', 'group2');
  sums.defineDone();

  do while (not hash_loaded);
    set have end=hash_loaded;
    sums.ref();                * adds value to internal sum of hash data record;
  end;

  do while (not last_have);
    set have end=last_have;
    sums.sum(sum:sum);         * retrieve group sum.;
    sum = sum - value;         * subtract from group sum;
    output;
  end;

  stop;
run;

Документация SAS касается SUMIN C и имеет некоторые примеры

Вопрос не касается этой концепции:

  • Для каждой строки вычислите сумму уровня 2, которая исключает уровень 3, в котором эта строка находится в

Решение на основе га sh потребует отслеживания каждые два уровня и суммы трех уровней:


data want2;
  if 0 then set have; * prep pdv;

  declare hash T2 (suminc:'value');   * hash for two (T)iers;
  T2.defineKey('group1', 'group2');   * one hash record per combination of group1, group2;
  T2.defineDone();

  declare hash T3 (suminc:'value');             * hash for three (T)iers;
  T3.defineKey('group1', 'group2', 'group3');   * one hash record per combination of group1, group2, group3;
  T3.defineDone();

  do while (not hash_loaded);
    set have end=hash_loaded;
    T2.ref();                * adds value to internal sum of hash data record;
    T3.ref();
  end;

  T2_cardinality = T2.num_items;
  T3_cardinality = T3.num_items;    

  put 'NOTE: |T2| = ' T2_cardinality;
  put 'NOTE: |T3| = ' T3_cardinality;

  do while (not last_have);
    set have end=last_have;
    T2.sum(sum:t2_sum);         
    T3.sum(sum:t3_sum);
    sum = t2_sum - t3_sum;
    output;
  end;

  stop;

  drop t2_: t3:;
run;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...