有没有比 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
并且您可以结合上述两种方法来生成用户定义的格式,该格式将为您装箱。
- 创建素材箱以设置用户定义的格式。这种方法的一个缺点是它需要你提前知道数据的范围。
- 通过 PROC FCMP 使用用户定义的函数。
- 使用手动计算
我在下面说明了 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;
我有一个美元金额列,我需要将其分成 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
并且您可以结合上述两种方法来生成用户定义的格式,该格式将为您装箱。
- 创建素材箱以设置用户定义的格式。这种方法的一个缺点是它需要你提前知道数据的范围。
- 通过 PROC FCMP 使用用户定义的函数。
- 使用手动计算
我在下面说明了 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;