【问题标题】:SAS: Rename variables in merge according to original datasetSAS:根据原始数据集重命名合并中的变量
【发布时间】:2018-02-02 01:08:30
【问题描述】:

我有两个数据集,一个是男性,一个是女性,它们包含相同的变量。我需要按组找出每个变量的性别百分比差异。

数据集看起来像这样,但包含更多变量和组,

| Group | Sex | VarA | VarB |
|-------+-----+------+------|
|     1 | F   |    8 |    5 |
|     2 | F   |    6 |    3 |
|     3 | F   |    7 |    0 |
|-------+-----+------+------|

| Group | Sex | VarA | VarB |
|-------+-----+------+------|
|     1 | M   |    9 |    7 |
|     2 | M   |    8 |    5 |
|     3 | M   |    6 |    3 |
|-------+-----+------+------|

我需要的结果是这样的:

| Group | percent_diffA | percent_diffB |
|-------+---------------+---------------|
|     1 |  -0.117647059 |  -0.333333333 |
|     2 |  -0.285714286 |          -0.5 |
|     3 |   0.153846154 |            -2 |
|-------+---------------+---------------|

我可以通过重命名每个变量的合并来解决这个问题。

data difference;
  merge
    females (rename = (VarA = VarA_F VarB = VarB_F)
    males   (rename = (VarA = VarA_M VarB = VarB_M)
    ;
  by group;

  percent_diffA = (VarA_F - VarA_M) / ( (VarA_F + VarA_M) / 2 );
  percent_diffB = (VarB_F - VarB_M) / ( (VarB_F + VarB_M) / 2 );

  drop sex;
run;

但是,这种方法需要我手动重命名所有内容。使用多个变量,重命名语句变得很麻烦。不幸的是,这个计算被插入到一些旧代码中,所以重命名原始数据集是不切实际的。

我想知道是否有另一种更简单的方法来解决这个问题。

编辑:我已经更新了变量名,因为这似乎引起了人们的困惑。它们最初被称为Var1Var2。他们现在是VarAVarB。真正的变量名称是描述性的,例如body_weight_ggonadal_somatic_index。变量不是简单地用序号列出的。

【问题讨论】:

  • 双重转置并在 ID 语句中使用两个变量以便自动重命名?或者将数据结构更改为一般的长数据结构可能会更容易整体使用,但可能不适合您的流程。

标签: sas


【解决方案1】:

对于包含按顺序编号的变量的数据集,有用于重命名整个变量范围的变量列表语法:

此示例创建具有 100 个变量的示例。

data have1 have2;
  do group = 1 to 100;
    sex = 'M';
    array var(100);
    do _n_ = 1 to dim(var);
      var(_n_) = ceil (25 * ranuni(123));
    end;
    if group ne 42 then output have1;
    sex = 'F';
    do _n_ = 1 to dim(var);
      var(_n_) = ceil (25 * ranuni(123));
    end;
    if group ne 100-42 then output have2;
  end;
run;

rename 选项适用于所有 100 个变量。

data want;
  merge 
    have1(rename=var1-var100=mvar1-mvar100 in=_M)
    have2(rename=var1-var100=fvar1-fvar100 in=_F)
  ;

  by group;

  if _M & _F & first.group & last.group then do;

    array one mvar1-mvar100;
    array two fvar1-fvar100;
    array results result1-result100; 

    do i = 1 to dim(results);
      diff = one(i) - two(i);
      mean = mean (one(i), two(i));
      results(i) = diff / mean * 100;
    end;

  end;

  keep group result:;
run;

【讨论】:

    【解决方案2】:

    Shenglin 的回答是对 SQL 的简洁明了的使用。 另一种方法是构造一个宏变量,指定要在重命名 DSO(数据集选项)中使用的重命名。这可以通过对包含列名的字典表的 SQL 查询来完成。

    * This macro creates the macro variable rename_suffix, to be used in a rename statement or data set option ;
    * It will be of form: var1 = var1_suffix var2 = var2_suffix ... ;
    * &inset is the input set. &suffix is the suffix to added to all variables except for the variables specified in &keys. ; 
    * &keys variables should be given each in quotation marks, and separated by spaces. ;
    %macro rename_list(inset, suffix, keys) ;
        %global rename_&inset ; * So that this macro variable is accessable outside the macro ;
        proc sql ;
            select strip(name) || ' = ' || strip(name) || "_&suffix"
                into :rename_&inset separated by ' '
                from sashelp.vcolumn /* dictionary.columns can be used in place of sashelp.vcolumn */
                    where libname = 'WORK' & memname = "%sysfunc(upcase(&inset))" 
                          & upcase(strip(name)) not in (' ' %sysfunc(upcase(&keys)));   * The ' ' is included, so there is no error if no keys are given ;
        quit ;
    %mend rename_list ; 
    
    %rename_list(females, F, 'GROUP' 'SEX')
    %rename_list(males  , M, 'GROUP' 'SEX')
    %put &rename_females ; * Check that the macro variables are correct ;
    %put &rename_males ;
    
    %macro pct_diff(num) ;
        percent_diff&num = (Var&num._F - Var&num._M) / ( (Var&num._F + Var&num._M) / 2 ) ;
    %mend pct_diff ;
    
    data difference ;
        merge females(rename = (&rename_females), drop = sex) 
              males  (rename = (&rename_males  ), drop = sex) ;
        by group ;
    
        pct_diff(1) ;
        pct_diff(2) ;
    run ;
    dm 'vt difference';
    

    percent_diff 变量的创建也可以用宏来缩短(如图所示)。如果您有大量和/或可变数量的变量要比较,那么您可以通过自动检测比较的数量来进一步缩短它,方法是运行相同的 SQL 查询并将 select into 部分修改为

    select count(name) into :varct trimmed
    

    统计变量个数,然后在数据步骤中使用do循环:

        do i = 1 to &varct ;
            %pct_diff(i) ;
        end ;
    

    【讨论】:

      【解决方案3】:

      在 proc sql 中使用表别名来避免名称更改:

      proc sql;
         select a.group,(a.var1-b.var1)/((a.var1+b.var1)/2) as percent_diff1, 
         (a.var2-b.var2)/((a.var2+b.var2)/2) as percent_diff2
         from female as a,male as b
         where a.group=b.group;
      quit;
      

      【讨论】:

      • 恐怕我看不出这有什么帮助,因为仍然需要明确写出每个变量。这怎么不完全类似于我给出的数据步骤示例?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多