有没有比 Case/When 更好的方法将数字列分割成统一的集合?

Is there a better way to segment a numeric column into uniform sets than Case/When?

我有一个美元金额列,我需要将其分成 1000 美元的部分 - 所以 0-999 美元、1,000-1,999 美元等。 我可以使用 Case/When,但是我必须创建非常多的组。 有没有更有效的方法来做到这一点? 谢谢!

当然。这是用户定义格式的一个很好的用例。

proc format;
  value segment
    0-<1000 = '0-1000'
    1000-<2000 = '1000s'
    2000-<3000 = '2000s'
   ;
quit;

如果数字太大写不出来,用代码写出来!

data segments;
  retain 
    fmtname 'segment'
    type 'n'       /* numeric format */
    eexcl 'Y'    /* exclude the "end" match, so 0-1000 excluding 1000 itself */
    ;
  do start = 0 to 1e6 by 1000;
    end = start + 1000;
    label = catx('- <',start,end);   * what you want this to show up as;
    output;
  end;
run;

proc format cntlin=segments;
quit;

然后您可以使用 segment = put(dollaramt,segment.); 来分配段的值,或者如果您只是在 PROC SUMMARY 或类似的地方使用它,则只应用格式 format dollaramt segment.;

你可以只用算术。例如,您可以将它们转换为 $1,000 范围的上限。

up_to = 1000*ceil(dollar/1000);

让我们编一些示例数据:

data test;
 do dollar=0 to 5000 by 500 ;
   up_to = 1000*ceil(dollar/1000);
   output;
 end;
run;

结果:

Obs    dollar    up_to

  1        0         0
  2      500      1000
  3     1000      1000
  4     1500      2000
  5     2000      2000
  6     2500      3000
  7     3000      3000
  8     3500      4000
  9     4000      4000
 10     4500      5000
 11     5000      5000

并且您可以结合上述两种方法来生成用户定义的格式,该格式将为您装箱。

  1. 创建素材箱以设置用户定义的格式。这种方法的一个缺点是它需要你提前知道数据的范围。
  2. 通过 PROC FCMP 使用用户定义的函数。
  3. 使用手动计算

我在下面说明了 1 和 3 的解决方案版本。 #2 需要 PROC FCMP 但我认为使用纯数据步骤会更简单。

data thousands_format;
fmtname = 'thousands_fmt';
type = 'N';
do Start = 0 to 10000 by 1000;
    END = Start + 1000 - 1;
    label = catx(" - ", put(start, dollar12.0), put(end, dollar12.0));
    output;
end;
run;

proc format cntlin=thousands_format;
run;

data demo;
do i=100 to 10000 by 50;
     custom_format = put(i, thousands_fmt.);
     manual_format = catx(" - ", put(floor(i/1000)*1000, dollar12.0), put((ceil(i/1000))*1000-1, dollar12.0));
output;
end;
run;