我想做什么:我需要为变量的每个值标签创建一个新变量并进行一些重新编码。我从SPSS文件中输出了所有值标签(参见示例)。
示例:
proc format; library = library ;
value SEXF
1 = 'Homme'
2 = 'Femme' ;
value FUMERT1F
0 = 'Non'
1 = 'Oui , occasionnellement'
2 = 'Oui , régulièrement'
3 = 'Non mais j''ai déjà fumé' ;
value ... (many more with different amount of levels)
新的变量名称将是没有F且具有下划线+级别的实际名称(例如:FUMERT1F级别0将变为FUMERT1_0)。
之后,我需要重新编码此模式的变量:
data ds; set ds;
FUMERT1_0=0;
if FUMERT1=0 then FUMERT1_0=1;
FUMERT1_1=0;
if FUMERT1=1 then FUMERT1_1=1;
FUMERT1_2=0;
if FUMERT1=2 then FUMERT1_2=1;
FUMERT1_3=0;
if FUMERT1=3 then FUMERT1_3=1;
run;
任何帮助将不胜感激:)
编辑:来自Joe和data_null_的答案都有效,但stackoverflow不会让我给出多个正确答案。
答案 0 :(得分:2)
更新以在每个名称的末尾添加_下划线。看起来PROC TRANSREG没有选项在变量名和类变量的值之间加上下划线,所以我们可以只进行临时重命名。创建重命名name = newname对以将类变量重命名为以下划线结尾并重命名它们。 CAT函数和SQL转换为宏变量。
data have;
call streaminit(1234);
do caseID = 1 to 1e4;
fumert1 = rand('table',.2,.2,.2) - 1;
sex = first(substrn('MF',rand('table',.5),1));
output;
end;
stop;
run;
%let class=sex fumert1;
proc transpose data=have(obs=0) out=vnames;
var &class;
run;
proc print;
run;
proc sql noprint;
select catx('=',_name_,cats(_name_,'_')), catx('=',cats(_name_,'_'),_name_), cats(_name_,'_')
into :rename1 separated by ' ', :rename2 separated by ' ', :class2 separated by ' '
from vnames;
quit;
%put NOTE: &=rename1;
%put NOTE: &=rename2;
%put NOTE: &=class2;
proc transreg data=have(rename=(&rename1));
model class(&class2 / zero=none);
id caseid;
output out=design(drop=_: inter: rename=(&rename2)) design;
run;
%put NOTE: _TRGIND(&_trgindn)=&_trgind;
首先尝试: 看看你提供的代码和Joe的输出我真的不了解格式的必要性。在我看来,你只想为类变量列表创建虚拟变量。这可以通过TRANSREG来完成。
data have;
call streaminit(1234);
do caseID = 1 to 1e4;
fumert1 = rand('table',.2,.2,.2) - 1;
sex = first(substrn('MF',rand('table',.5),1));
output;
end;
stop;
run;
proc transreg data=have;
model class(sex fumert1 / zero=none);
id caseid;
output out=design(drop=_: inter:) design;
run;
proc contents;
run;
proc print data=design(obs=40);
run;
答案 1 :(得分:1)
代码的一个不错的替代方法是使用proc transpose
。它不会让你在非1个单元格中获得0,但这些很容易获得。它的缺点是它使得变量更难以按特定顺序排列。
基本上,将一次转置为垂直,然后使用连接到变量值的旧变量名作为新变量名转置回来。提示数据 null ,以便在最近的SAS-L帖子中显示此功能。如果您的SAS版本不支持PROC TRANSPOSE中的连接,请事先在数据步骤中进行连接。
我使用PROC EXPAND
显示然后将缺失设置为0,但如果您没有ETS或PROC EXPAND
太慢,您也可以在数据步骤中执行此操作。还有其他方法可以做到这一点 - 包括使用0s pre-proc-transpose设置数据集 - 如果你有一个需要的复杂场景,这可能会成为一个很好的单独问题。
data have;
do caseID = 1 to 1e4;
fumert1 = rand('Binomial',.3,3);
sex = rand('Binomial',.5,1)+1;
output;
end;
run;
proc transpose data=have out=want_pre;
by caseID;
var fumert1 sex;
copy fumert1 sex;
run;
data want_pre_t;
set want_pre;
x=1; *dummy variable;
run;
proc transpose data=want_pre_t out=want delim=_;
by caseID;
var x;
id _name_ col1;
copy fumert1 sex;
run;
proc expand data=want out=want_e method=none;
convert _numeric_ /transformin=(setmiss 0);
run;
答案 2 :(得分:1)
对于此方法,您需要使用两个概念:cntlout
中的proc format
数据集和代码生成。这种方法可能比我提出的其他选项更快(因为它只通过数据一次),但它依赖于变量名< - >格式关系很简单。如果不是,则需要稍微复杂的变化;你应该发布这个效果,这可以修改。
首先,cntlout
中的proc format
选项生成格式目录内容的数据集。这不是唯一的方法,但这是一个非常简单的方法。像创建格式时一样指定适当的libname,但不是制作一个,而是将数据集转储出来,并且可以将其用于其他目的。
其次,我们创建一个宏来执行您的操作一次(使用name_value名称创建一个变量,然后将其分配给适当的值),然后使用proc sql
对该宏进行一系列调用,对于cntlout
数据集中的每一行一次。注意 - 如果您的格式库包含数据集中不存在的变量格式,或者它没有良好的整洁关系,那么您可能需要where
子句或其他一些修改你的例子。然后我们只是在数据步骤中进行这些调用。
*Set up formats and dataset;
proc format;
value SEXF
1 = 'Homme'
2 = 'Femme' ;
value FUMERT1F
0 = 'Non'
1 = 'Oui , occasionnellement'
2 = 'Oui , régulièrement'
3 = 'Non mais j''ai déjà fumé' ;
quit;
data have;
do caseID = 1 to 1e4;
fumert1 = rand('Binomial',.3,3);
sex = rand('Binomial',.5,1)+1;
output;
end;
run;
*Dump formats into table;
proc format cntlout=formats;
quit;
*Macro that does the above assignment once;
%macro spread_var(var=, val=);
&var._&val.= (&var.=&val.); *result of boolean expression is 1 or 0 (T=1 F=0);
%mend spread_var;
*make the list. May want NOPRINT option here as it will make a lot of calls in your output window otherwise, but I like to see them as output.;
proc sql;
select cats('%spread_var(var=',substr(fmtname,1,length(Fmtname)-1),',val=',start,')')
into :spreadlist separated by ' '
from formats;
quit;
*Actually use the macro call list generated above;
data want;
set have;
&spreadlist.;
run;