【问题标题】:SAS summary statistic from a dataset来自数据集的 SAS 汇总统计
【发布时间】:2018-02-04 02:51:54
【问题描述】:

数据集如下所示:

colx      coly    colz  
0         1       0      
0         1       1      
0         1       0       

需要的输出:

Colname      value    count

colx         0        3
coly         1        3
colz         0        2
colz         1        1

以下代码完美运行...

ods output onewayfreqs=outfreq;

proc freq data=final;
  tables colx coly colz / nocum nofreq;
run;

data freq;
  retain colname column_value;
  set outfreq;
  colname = scan(tables, 2, ' ');
  column_Value = trim(left(vvaluex(colname)));
  keep colname column_value frequency percent;
run;

...但我认为这不是有效的。假设我有 1000 列,在所有 1000 列上运行 prof freq 效率不高。有没有其他有效的方法不使用 proc freq 来完成我想要的输出?

【问题讨论】:

  • 我认为这是最好的。您可以使用 _all_ 关键字而不是键入所有列名。 (tables _all_ / nocum nofreq;)
  • 这在什么意义上没有效率?你只运行一次 proc freq 。可能可以编写一个使用稍微少一点内存的等效数据步骤,但除非证明这对您来说是一个限制因素,否则我不会打扰。
  • 我觉得带有 proc freq 的 odsoutput 正在减慢并创建大量日志和输出。想想 10,000 个变量和百万条记录。我觉得应该有另一种方法来实现这一点,数组似乎很合适

标签: sas sas-macro


【解决方案1】:

计算频率计数的最有效机制之一是通过 suminc 标签为引用计数设置的哈希对象。

“哈希对象 - 维护密钥摘要”的 SAS 文档演示了单个变量的技术。下面的示例更进一步,计算数组中指定的每个变量。 suminc:'one' 指定每次使用 ref 都会将 one 的值添加到内部引用总和中。在迭代输出的不同键时,通过sum 方法提取频率计数。

* one million data values;

data have;
  array v(1000);
  do row = 1 to 1000;
    do index = 1 to dim(v);
      v(index) = ceil(100*ranuni(123));
    end;
    output;
  end;
  keep v:;
  format v: 4.;
run;

* compute frequency counts via .ref();    

data freak_out(keep=name value count);
  length name $32 value 8;

  declare hash bins(ordered:'a', suminc:'one');
  bins.defineKey('name', 'value');
  bins.defineData('name', 'value');
  bins.defineDone();

  one = 1;

  do until (end_of_data);
    set have end=end_of_data;
    array v v1-v1000;
    do index = 1 to dim(v);
      name = vname(v(index));
      value = v(index);
      bins.ref();
    end;
  end;

  declare hiter out('bins');
  do while (out.next() = 0);
    bins.sum(sum:count);
    output;
  end;
run;

注意Proc FREQ 使用标准语法,变量可以是字符和数字的混合,并且具有许多通过选项指定的附加功能。

【讨论】:

    【解决方案2】:

    我认为您的代码中最耗时的部分是生成 ODS 报告。您可以在应用频率之前转置数据。下面的示例在几秒钟内完成了包含 1000 个变量的 1000 行的任务。如果您使用 ODS 执行此操作,则可能需要更长的时间。

    data dummy;
        array colNames [1000] col1-col1000;
        do line = 1 to 1000;
            do j = 1 to dim(colNames);
                colNames[j] = int(rand("uniform")*100);
            end;
            output;
        end;
        drop j;
    run;
    
    proc transpose 
        data = dummy 
        out = dummyTransposed (drop = line rename = (_name_ = colName col1 = value))
        ;
        var col1-col1000;
        by line;
    run;
    
    proc freq data = dummyTransposed noprint;
        tables colName*value / out = result(drop = percent);
    run;
    

    【讨论】:

      【解决方案3】:

      也许 cmets 的这句话才是真正的问题。

      我觉得带有 proc freq 的 odsoutput 正在减慢并创建 巨大的日志和输出。想想 10,000 个变量和百万条记录。 我觉得应该有另一种方法来完成这个和数组 好像很合适

      如果您不想要,可以告诉 ODS 不要生成打印输出。

      ods exclude all ;
      ods output onewayfreqs=outfreq;
      proc freq data=final;
        tables colx coly colz / nocum nofreq;
      run;
      ods exclude none ;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-05
        • 2019-08-18
        相关资源
        最近更新 更多