你好,我正在处理以下问题。我有一个调查,你可以标记几个答案,以及添加您自己的答案。例如,假设我们有3个答案: a,b,c。人nr 1标记答案a,人nr 2标记答案b,c,人nr 3标记a,c。我希望收到结果:"a“标记了2次。为此,我尝试删除重复的答案,并创建一个宏变量来存储这些唯一的答案: a,b,c。
我已经将所有调查问题重命名为v1-v&n_que。其中,n_que是一个宏变量,用于保存有关调查中问题数量的信息。我试图将所有答案分成一个表(使用前面的例子,我将得到一个具有下列值的列):a,b,c,a,c。然后我想对这些数据进行排序,并删除重复的数据。我尝试过以下几种方法:
%macro coll_ans(lib, tab);
%do _i_ = 1 %to &n_que. %by 1;
%global betav&_i_.;
proc sql noprint;
select distinct v&_i_. into :betav&_i_. separated by ', '
from &lib..&tab.
where v&_i_. ^= ' ';
quit;
data a&_i_.;
%do _j_ = 1 %to %sysfunc(countw(%quote(&&&betav&_i_.), ',')) %by 1;
text = %scan(%quote(&&&betav&_i_), &_j_., ',');
output;
%end;
run;
%end;
%mend coll_ans;值得一提的是,如果有人选择了一个以上的答案,例如a和b,答案用逗号分隔,这就是为什么我选择这个分隔符来统一记录。我尝试了几乎所有的方法,将%quote更改为%bquote,%superq,写入&&而不是&,但我一直收到以下错误(其他40个错误中的第一个):
ERROR: The function NO is unknown, or cannot be accessed.“否”是调查中第一个问题的答案之一,完整的答案是:否(转到第九个问题)。值得一提的是,整个调查都是用波兰语进行的,但我使用了正确的编码,所以我不认为这会造成一些问题(希望如此)。
我将感谢所有的建议,因为我遇到了一堵不可逾越的墙。
发布于 2018-05-27 06:48:51
我猜你有一个这样的数据集:
data have ;
input id v1 : $8. v2 : $8.;
cards ;
1 a a
2 b,c b
3 a,c c
;您可以转置数据集,使其每个ID-variable-value有一条记录。
data tran (keep=id VarName Value);
set have ;
array vars{*} v1 v2 ;
do i=1 to dim(vars) ;
Varname=vname(vars{i}) ;
do j=1 to countw(vars{i},',') ;
Value=scan(vars{i},j,',') ;
output ;
end ;
end ;
run ;输出数据集如下所示:
id Varname Value
1 v1 a
1 v2 a
2 v1 b
2 v1 c
2 v2 b
3 v1 a
3 v1 c
3 v2 c您可以使用PROC FREQ或SQL来获取计数。
proc freq data=tran ;
tables varname*value/missing list ;
run ;输出
Varname Value Frequency
v1 a 2
v1 b 1
v1 c 2
v2 a 1
v2 b 1
v2 c 1发布于 2018-05-27 19:29:59
首先,如果你张贴你收到调查数据的格式会更好,因为这将决定最简单/最快的总体方法。
此外,作为一般规则,最好在非宏SAS代码中获得正确的输入和输出,然后使用宏优化过程等。这样更容易调试-即使对于长期使用宏的人也是如此。:)
也就是说,从Proc SQL代码中可以看出:
答:您在单个分隔文本字段中收到答案,例如" a,b,c“或"b,c”或"a,b,z“
*** example data;
data work.answers;
length answer $10.;
input answer;
datalines;
a,b,c
a
b
b,c
NO
a,b,z
n
run;
*** example valid answer entries;
data work.valid;
length valid $10.;
input valid;
datalines;
a
b
c
NO
YES
run;b.您希望验证每个答案条目并生成计数,如下所示:
NO 1
YES 0
a 3
b 4
c 2 在SAS中有很多方法可以做到这一点,但是对于解析标记化的文本数据来说,使用hash对象的去重复查找表是很方便的。下面的代码还将以下内容打印到日志中以进行调试/验证...
answer=a,b,c num_answers=3 val=a val=b val=c validated=a,b,c
answer=a num_answers=1 val=a validated=a
answer=b num_answers=1 val=b validated=b
answer=b,c num_answers=2 val=b val=c validated=b,c
answer=NO num_answers=1 val=NO validated=NO
answer=a,b,z num_answers=3 val=a val=b val=z -invalid validated=a,b, validated=a,b,
answer=n num_answers=1 val=n -invalid validated= validated= 一旦您掌握了hash对象的声明语法,它就非常符合逻辑且相对较快。当然,您还可以添加验证规则-例如大写和小写条目...
*** first, de-duplicate your lookup table. ;
proc sort data=work.valid nodupkey;
by valid;
run;
data _null_;
length valid $10. answer_count 4. count 4. validated $10.;
retain count 0;
*** initialize & load hash object ;
if _N_ = 1 then do;
declare hash h(multidata: 'n', ordered: 'y');
rc = h.defineKey('valid');
rc = h.defineData('valid','count');
rc = h.defineDone();
do until(eof1);
set work.valid end=eof1;
h.add();
end;
end;
*** now process questions/answers;
do until(eof);
*** read each answer;
set answers end=eof;
num_answers=countw(answer);
putlog answer= num_answers= @;
*** parse each answer entry;
validated=answer;
do i=1 to num_answers;
val=scan(answer,i);
putlog val= @;
*** (optional) keep track of total #answers: valid + invalid;
answer_count+1;
*** check answer entry in lookup table;
rc= h.find(key:val);
*** if entry NOT in lookup table, remove from validated answer;
if rc ne 0 then do;
putlog "-invalid " @;
validated=tranwrd(validated,trim(val),' ');
end;
*** if answer found, increment counter in lookup table;
else do;
count+1;
h.replace();
end;
end;
putlog validated=;
end;
*** save table of answer counts to disk;
if eof then h.output(dataset: 'work.counts');
run;https://stackoverflow.com/questions/50542911
复制相似问题