我希望有人可以帮我解决这个问题。我试图采取一个字符串变量,其中包含一系列分隔的选择列表响应。在单个变量中可能没有响应,一个响应(例如,1234)或几个响应(例如,1234; 9876)。不同的选项始终用分号(;)分隔。我想根据分隔符将这个单个变量拆分成多个变量。
例如,reason = 1234; 9876 - > reason1 = 1234,reason2 = 9876
传统上我使用扫描功能以手动方式完成了这项工作。问题是我有(在这种情况下)10个选择列表项连接在一个字符串中。
data want;
set got;
length reason1-reason10 $10;
if reasons ne ' ' then reason1=scan(reasons, 1, ';');
if reasons ne ' ' then reason2=scan(reasons, 2, ';');
if reasons ne ' ' then reason3=scan(reasons, 3, ';');
...
run;
依旧......
我觉得数组会大大简化这个过程。但是,我现在只是学习如何使用数组。关于如何使用更高效的代码拆分此字符串变量的任何建议都将非常感激。谢谢!
答案 0 :(得分:3)
解决此问题的最佳方法因数据集的大小和复杂程度而异 - 可能存在多少可能的变量?
如果有一个小的,已知的前面数量的变量,那么你的方法很好。数组有点帮助:
data got;
informat reasons $30.;
input reasons $;
datalines4;
123;456;789;101112
456;789;101112;131415
;;;;
run;
data want;
set got;
length reason1-reason10 $10;
array reason(10) $;
do _i = 1 to dim(reason);
reason[_i] = scan(reasons,_i,';');
end;
run;
你甚至不必检查它是否缺失,SCAN会表现得很好。
如果您不确定变量的数量是多少(如果永远不会达到'最大值'),PROC TRANSPOSE
会更好。
首先为每个扫描值添加一行,所有这些都在一个变量中。然后转置它。
添加id
变量以简化此操作:
data got;
informat reasons $30.;
input id reasons $;
datalines4;
1 123;456;789;101112
2 456;789;101112;131415
;;;;
run;
data got_pret;
set got;
do _i = 1 to countw(reasons,';');
reason=scan(reasons,_i,';');
output;
end;
keep reason id;
run;
proc transpose data=got_pret out=want prefix=reason;
by id;
var reason;
run;
这样做的好处是不需要提前知道有多少。这又是一个步骤,因此对于巨大的数据集,它可能不太受欢迎(尽管您可以使用数据步骤view
来保存其中一些)。