从格式值创建新变量

时间:2016-02-09 20:30:02

标签: sas

我想做什么:我需要为变量的每个值标签创建一个新变量并进行一些重新编码。我从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不会让我给出多个正确答案。

3 个答案:

答案 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;

enter image description here

首先尝试: 看看你提供的代码和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;

enter image description here

答案 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;