SAS 对不在一个组中的观察值求和,按多个组

雅克

这篇文章遵循这一点:SAS sum Observations not in a group, by group遗憾的是,我的最小示例有点太小了,我无法在我的数据上使用它。

这是一个完整的案例示例,我所拥有的是:

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;

对于每个组,我想要一个新变量“sum”,其中包含相同子组(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;

我的目标是使用 datasteps 或 proc sql(在大约 3000 万次观察和 proc 均值上执行此操作,SAS 中的此类操作似乎比以前类似计算中的慢)。

我在链接帖子中提供的解决方案的问题是使用列的总值,我不知道如何通过使用子组中的总值来更改它。请问有什么想法吗?

理查德

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 可能比哈希解决方案慢,但是比那些了解涉及哈希的 SAS DATA Step 的人理解 SQL 代码的人更多(这可以比 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 文档涉及SUMINC并有一些示例

这个问题没有解决这个概念:

  • 对于每一行,计算排除该行所在的第 3 层的第 2 层总和

基于散列的解决方案需要跟踪每两个级别和三个级别的总和:


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;

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章