【问题标题】:Assign missing variables values based on distribution SAS根据分布 SAS 分配缺失变量值
【发布时间】:2016-07-12 04:21:33
【问题描述】:

我想根据其组的频率分布为具有空白尺寸的 ID 分配尺寸。

数据集 A 包含我的数据的快照:

ID  Group   Size
1   A       Large
2   B       Small
3   C       Small
5   D       Medium
6   C       Large
7   B       Medium
8   B       -

数据集 B 显示了各组中大小的频率分布:

Group   Small   Medium  Large
A       0.31    0.25    0.44
B       0.43    0.22    0.35
C       0.10    0.13    0.78
D       0.29    0.27    0.44

对于 ID 8,我们知道它有 43% 的概率是“小”,有 22% 的概率是“中”,35% 的概率是“大”。这是因为这些是 B 组的大小分布。

如何根据数据集 B 中的组分布为 ID 8(和其他空白 ID)分配大小?我正在使用 SAS 9.4。宏、SQL,什么都可以!

【问题讨论】:

    标签: sas


    【解决方案1】:

    table 分发版非常适合这种情况。这里的最后一个数据步表明;在此之前,我设置了随机创建数据并确定频率表,所以如果你已经这样做了,你可以跳过它。

    请参阅 Rick Wicklin 的关于 simulating multinomial data 的博客,了解其他用例中的示例(以及有关该函数的更多信息)。

    *Setting this up to help generate random data;
    proc format;
      value sizef
      low - 1.3 = 'Small'
      1.3 <-<2.3  = 'Medium'
      2.3  - high = 'Large'
    ;
    quit;
    
    *Generating random data;
    data have;
      call streaminit(7);
      do id = 1 to 1e5;
        group = byte(65+rand('Uniform')*4);   *A = 65, B = 66, etc.;
        size  = put((rank(group)-66)*0.5 + rand('Uniform')*3,sizef.);  *Intentionally making size somewhat linked to group to allow for differences in the frequency;
        if rand('Uniform') < 0.05 then call missing(size); *A separate call to set missingness;
        output;
      end;
    run;
    
    proc sort data=have;
      by group;
    run;
    
    title "Initial frequency of size by group";
    proc freq data=have;
      by group;
      tables size/list out=freq_size;
    run;
    title;
    
    *Transpose to one row per group, needed for table distribution;
    proc transpose data=freq_size out=table_size prefix=pct_;
      var percent;
      id size;
      by group;
    run;
    
    
    data want;
      merge have table_size;
      by group;
      array pcts pct_:;  *convenience array;
    
      if first.group then do _i = 1 to dim(pcts);  *must divide by 100 but only once!;
        pcts[_i] = pcts[_i]/100;
      end;
    
      if missing(size) then do;
        size_new = rand('table',of pcts[*]);   *table uses the pcts[] array to tell SAS the table of probabilities;
        size = scan(vname(pcts[size_new]),2,'_');
      end;
    run;
    
    
    
    title "Final frequency of size by group";
    proc freq data=want;
      by group;
      tables size/list;
    run;
    title;
    

    【讨论】:

      【解决方案2】:

      您也可以使用随机值和一些 if-else 逻辑来执行此操作:

      proc sql;
          create table temp_assigned as select
              a.*, rand("Uniform") as random_roll, /*generate a random number from 0 to 1*/
              case when missing(size) then
                  case when calculated random_roll < small then small
                       when calculated random_roll < sum(small, medium) then medium
                       when calculated random_roll < sum(small, medium, large) then large
                  end end as value_selected, /*pick the value of the size associated with that value in each group*/
              coalesce(case when calculated value_selected = small then "Small"
                           when calculated value_selected = medium then "Medium"
                           when calculated value_selected = large then "Large" end, size) as group_assigned /*pick the value associated with that size*/
              from temp as a
              left join freqs as b
              on a.group = b.group;
      quit;
      

      显然,您可以在不创建 value_selected 变量的情况下执行此操作,但我认为出于演示目的显示它会有所帮助。

      【讨论】:

        猜你喜欢
        • 2021-08-08
        • 2016-12-04
        • 2013-09-05
        • 1970-01-01
        • 1970-01-01
        • 2019-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多