Dataframe SAS汇总观察值不在一组中,按组

Dataframe SAS汇总观察值不在一组中,按组,dataframe,sas,Dataframe,Sas,我有一个数据集: data have; input group $ value; datalines; A 4 A 3 A 2 A 1 B 1 C 1 D 2 D 1 E 1 F 1 G 2 G 1 H 1 ; run; 第一个变量是组标识符,第二个变量是值 对于每个组,我需要一个新变量“sum”,该变量包含列中所有值的总和,除了观察值所在的组 我的问题是必须在近3000万次观测中做到这一点,因此效率很重要。 我发现使用数据步骤比使用过程更有效 最终的数据库应该如下所示: data

我有一个数据集:

data have;
   input group $ value;
   datalines;
A 4
A 3
A 2
A 1
B 1
C 1
D 2
D 1
E 1
F 1
G 2
G 1
H 1
;
run;
第一个变量是组标识符,第二个变量是值

对于每个组,我需要一个新变量“sum”,该变量包含列中所有值的总和,除了观察值所在的组

我的问题是必须在近3000万次观测中做到这一点,因此效率很重要。 我发现使用数据步骤比使用过程更有效

最终的数据库应该如下所示:

data want;
   input group $ value $ sum;
   datalines;
A 4 11
A 3 11
A 2 11
A 1 11
B 1 20
C 1 20
D 2 18
D 1 18
E 1 20
F 1 20
G 2 18
G 1 20
H 1 20
;
run;
你知道怎么做吗


编辑:我不知道这是否有问题,但我给出的例子是我问题的简化版本。在实际情况中,我有另外两个组变量,因此取整列的和并减去组中的和不是一个可行的解决方案。

我将把它分成两个不同的部分:

1.)您可以从使用PROC SQL获取组的总和开始


2.)然后使用一些IF/Then语句按组重新分配值

我将其分为两个不同的部分:

1.)您可以从使用PROC SQL获取组的总和开始

2.)然后使用一些IF/Then语句按组重新分配值

列中所有值的总和,观察值所在的组除外

指示必须进行两次数据传递:

  • 计算
    all\u sum
    和每个组的
    group\u sum

    哈希可以存储每个组的总和——通过指定的
    suminc:
    变量和
    .ref()
    方法调用计算。变量可以累加
    allsum
  • 为组的每一行计算
    allsum
    -
    group\u sum

    从哈希中检索
    group\u sum
    ,并从
    allsum
    中减去
  • 例如:

    data want;
      if 0 then set have; * prep pdv;
    
      declare hash sums (suminc:'value');
      sums.defineKey('group');
      sums.defineDone();
    
      do while (not hash_loaded);
        set have end=hash_loaded;
        sums.ref();                * adds value to internal sum of hash data record;
        allsum + value;
      end;
    
      do while (not last_have);
        set have end=last_have;
        sums.sum(sum:sum);         * retrieve groups sum. Do you hear the Dragnet theme too?;
        sum = allsum - sum;        * subtract from allsum;
        output;
      end;
    
      stop;
    run;
    
    要求

    列中所有值的总和,观察值所在的组除外

    指示必须进行两次数据传递:

  • 计算
    all\u sum
    和每个组的
    group\u sum

    哈希可以存储每个组的总和——通过指定的
    suminc:
    变量和
    .ref()
    方法调用计算。变量可以累加
    allsum
  • 为组的每一行计算
    allsum
    -
    group\u sum

    从哈希中检索
    group\u sum
    ,并从
    allsum
    中减去
  • 例如:

    data want;
      if 0 then set have; * prep pdv;
    
      declare hash sums (suminc:'value');
      sums.defineKey('group');
      sums.defineDone();
    
      do while (not hash_loaded);
        set have end=hash_loaded;
        sums.ref();                * adds value to internal sum of hash data record;
        allsum + value;
      end;
    
      do while (not last_have);
        set have end=last_have;
        sums.sum(sum:sum);         * retrieve groups sum. Do you hear the Dragnet theme too?;
        sum = allsum - sum;        * subtract from allsum;
        output;
      end;
    
      stop;
    run;
    

    直截了当的方法有什么错?无论你做什么,你都需要两次传球

    像这样。我包含了额外的变量,以便您可以看到值是如何派生的

    proc sql ;
     create table want as
      select a.*,b.grand,sum(value) as total, b.grand - sum(value) as sum
      from have a
         , (select sum(value) as grand from have) b
      group by a.group
     ;
    quit;
    
    结果:

    Obs    group    value    grand    total    sum
    
      1      A        3        21       10      11
      2      A        1        21       10      11
      3      A        2        21       10      11
      4      A        4        21       10      11
      5      B        1        21        1      20
      6      C        1        21        1      20
      7      D        2        21        3      18
      8      D        1        21        3      18
      9      E        1        21        1      20
     10      F        1        21        1      20
     11      G        1        21        3      18
     12      G        2        21        3      18
     13      H        1        21        1      20
    
    注意,作为GROUPBY子句,您拥有什么并不重要

    您真的需要输出所有原始观察结果吗?为什么不直接输出汇总表呢

    proc sql ;
     create table want as
      select a.group, b.grand - sum(value) as sum
      from have a
         , (select sum(value) as grand from have) b
      group by a.group
     ;
    quit;
    
    结果

    Obs    group    total    sum
    
     1       A        10      11
     2       B         1      20
     3       C         1      20
     4       D         3      18
     5       E         1      20
     6       F         1      20
     7       G         3      18
     8       H         1      20
    

    直截了当的方法有什么错?无论你做什么,你都需要两次传球

    像这样。我包含了额外的变量,以便您可以看到值是如何派生的

    proc sql ;
     create table want as
      select a.*,b.grand,sum(value) as total, b.grand - sum(value) as sum
      from have a
         , (select sum(value) as grand from have) b
      group by a.group
     ;
    quit;
    
    结果:

    Obs    group    value    grand    total    sum
    
      1      A        3        21       10      11
      2      A        1        21       10      11
      3      A        2        21       10      11
      4      A        4        21       10      11
      5      B        1        21        1      20
      6      C        1        21        1      20
      7      D        2        21        3      18
      8      D        1        21        3      18
      9      E        1        21        1      20
     10      F        1        21        1      20
     11      G        1        21        3      18
     12      G        2        21        3      18
     13      H        1        21        1      20
    
    注意,作为GROUPBY子句,您拥有什么并不重要

    您真的需要输出所有原始观察结果吗?为什么不直接输出汇总表呢

    proc sql ;
     create table want as
      select a.group, b.grand - sum(value) as sum
      from have a
         , (select sum(value) as grand from have) b
      group by a.group
     ;
    quit;
    
    结果

    Obs    group    total    sum
    
     1       A        10      11
     2       B         1      20
     3       C         1      20
     4       D         3      18
     5       E         1      20
     6       F         1      20
     7       G         3      18
     8       H         1      20
    

    关于“我发现使用数据步骤比使用过程更有效”,您尝试了什么代码?3000万行中有多少个不同的组?这不是为了这个特定的任务,我在计算大约6000万个观察值的计数变量,不记得两年前我使用的程序,因为我使用数据步骤完成了类似的任务。在我开始使用procs的时候,我花了至少2个小时才可以在不到30分钟的时间内对数据步骤做同样的事情。问题可能是RAM,计算是在RAM上只有8gb的服务器上进行的(不可能添加更多)。数据总是由
    组进行预排序吗
    ?多个分组变量如何改变您想要的?您是说在这种情况下需要多个和变量吗?关于“我发现使用数据步骤比使用过程更有效。”您尝试了什么代码?3000万行中有多少个不同的组?这不是为了这个特定的任务,我在计算大约6000万个观察值的计数变量,不记得两年前我使用的程序,因为我使用数据步骤完成了类似的任务。在我开始使用procs的时候,我花了至少2个小时才可以在不到30分钟的时间内对数据步骤做同样的事情。问题可能是RAM,计算是在RAM上只有8gb的服务器上进行的(不可能添加更多)。数据总是由
    组进行预排序吗
    ?多个分组变量如何改变您想要的?你是说在这种情况下需要多个和变量吗?谢谢你的回答。它在最小的示例中非常有效,但是我在多个组中使用它时遇到了问题。在我的例子中,我有3个级别的组,第一个级别是年,然后是区域,最后是区域内的组。datastep开头的简单by语句不起作用,因为在do-while循环中,它取整个数据库的总和。您知道如何修改代码以允许更多级别的组吗?请更改
    defineKey
    语句以列出所有组变量,
    sums.defineKey('byvar1','byvar2','byvar3')