【问题标题】:SAS: Replace rare levels in variable with new level "Other"SAS:用新级别“其他”替换变量中的稀有级别
【发布时间】:2019-04-18 14:04:44
【问题描述】:

我有一个很大的表,我想替换稀有值(对于这个例子,出现次数少于 10 但实际情况更复杂——它可能有 1000 个级别,而我只想有 15 个)。这个可能级别的列表可能会改变,所以我不想硬编码任何东西。

我的代码是这样的:

%let var = Make;

    proc sql;

    create table stage1_ as
        select &var.,
               count(*) as count
        from sashelp.cars
        group by &var.
        having count >= 10 
        order by count desc

    ;
    quit;

    /* Join table with table including only top obs to replace rare
       values with "other" category */
    proc sql;
    create table stage2_ as 
        select t1.*,
                case when t2.&var. is missing then "Other_&var." else t1.&var. end as &var._new
        from sashelp.cars t1 left join 
             stage1_ t2 on t1.&var. = t2.&var.
    ;
    quit;

    /* Drop old variable and rename the new as old */
    data result;
        set stage2_(drop= &var.);
        rename &var._new=&var.;
    run;

它可以工作,但不幸的是它不是很有效,因为它需要为每个变量进行连接(在实际情况下,我是在循环中进行的)。 有更好的方法吗?也许一些智能替换功能?

谢谢!!

【问题讨论】:

  • 对于字符变量的情况,比如将pqr映射pqr_new不是 10-最频繁(您的定义pqrrare) 值将更改为文字 "Other_pqr"。对于数字变量的情况,比如 xyz映射xyz_new,由于它是罕见的数值,将使用什么文字值来表示差异性?
  • 级别的数量并不是真正的问题,混乱会更多来自变量的数量。你要处理多少个变量?您想自动映射所有变量,还是只映射您指定的变量?

标签: sas


【解决方案1】:

您可能不想更改实际数据值。相反,请考虑为每个变量创建自定义格式,将稀有值映射到“其他”类别。

FREQ 过程 ODS 可用于捕获在单个表中列出的每个变量的计数和百分比。注意:Freqtable/out= 仅捕获最后列出的变量。这些计数可用于根据您要实施的“其他”规则构建格式。

data have;
  do row = 1 to 1000;
    array x x1-x10;
    do over x;
      if row < 600 
        then x = ceil(100*ranuni(123));
        else x = ceil(150*ranuni(123));
    end;
    output;
  end;
run;

ods output onewayfreqs=counts;

proc freq data=have ;
  table x1-x10;
run;

data count_stack;
  length name $32;
  set counts;
  array x x1-x10;
  do over x;
    name = vname(x);
    value = x;
    if value then output;
  end;
  keep name value frequency;
run;

proc sort data=count_stack;
  by name descending frequency ;
run;

data cntlin;
  do _n_ = 1 by 1 until (last.name);
    set count_stack;
    by name;
    length fmtname $32;
    fmtname = trim(name)||'top';
    start = value;
    label = cats(value);
    if _n_ < 11 then output;
  end;
  hlo = 'O';
  label = 'Other';
  output;
run;

proc format cntlin=cntlin;
run;

ods html;

proc freq data=have;
  table x1-x10;
  format
    x1 x1top.
    x2 x2top.
    x3 x3top.
    x4 x4top.
    x5 x5top.
    x6 x6top.
    x7 x7top.
    x8 x8top.
    x9 x9top.
    x10 x10top.
  ;
run; 

【讨论】:

  • 我接受了这个答案,因为我不清楚它的目的。它应该被永久更改,因为数据后来用于建模目的(在不同的环境中 - python)。
猜你喜欢
  • 2019-03-10
  • 1970-01-01
  • 1970-01-01
  • 2011-10-04
  • 2014-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-20
相关资源
最近更新 更多