根据包含代码本 - PROC SQL 的单独数据集中的变量更改一个数据集中的 SAS 变量标签/属性?PROC 数据集?

Changing SAS variable labels/attributes in one dataset based on variables in a separate dataset containing a codebook - PROC SQL? PROC DATASETS?

提问人:L.S. 提问时间:2/18/2022 更新时间:2/18/2022 访问量:839

问:

我问题的核心是 - 我可以使用 PROC SQL、PROC DATASETS 或其他命令根据另一个数据集中的数据直接修改一个数据集的元数据吗?如果是,您能告诉我更多关于使用什么代码或使用什么搜索词来试图弄清楚它的信息吗?

以下是背景和细节—— 我定期收到来自研究合作伙伴的研究结果数据导出(Excel),他们还为我提供了Excel中的密码本。结果数据文件始终包含相同的字段,但其数据表需要大量清理。我需要开发一个流程,将结果数据转换为可用的 SAS 数据集,包括标记变量和语法文件,用于创建和应用用户定义的格式。我想尽可能高效地做到这一点。理想情况下,我想要求 SAS 根据在 codebook 数据集中找到的变量名称 * 变量标签组合来更改结果数据集中的元数据/变量属性(特别是标签)。在我看来,一种方法是将两个 Excel 文件导入 SAS,然后使用 Concatenate 函数以新字符变量的形式编写语法,然后在结果数据集上运行的语法的数据步骤中使用该新变量的文本。具体说来:

*Use concatenate function to create variable containing syntax text;
data codebook_edit;
set codebook;
format Syntax_Label $2000.;
Syntax_Label=cat("label ", trim(Field_Name), " = '", trim(Field_Label), "';");
run;

然后,这将生成一个字符变量,其行如下所示:

label race = 'Race Ethnicity';
label sex = 'Sex assigned at birth';
label gender = 'Gender identity';

然后我会运行这个:

*Get syntax to label vars;
proc print data=codebook_edit noobs;
var Syntax_Label;
run;
*Apply labels;
data results_edit;
set results;
label race = 'Race Ethnicity';
label sex = 'Sex assigned at birth';
label gender = 'Gender identity';
run;

但是,我想知道是否有更好的方法可以做到这一点,因为我有数百个变量,并且宁愿不创建这么长的语法文件。例如,我是否可以使用 PROC SQL 或 PROC DATASETS 或其他命令根据码本中的数据直接修改研究结果数据集中的元数据,如果是,您能提供任何提示吗?谢谢

SAS 元数据 操作 数据 清理 proc-sql

评论

0赞 Tom 2/18/2022
他们正在将数据作为 XLSX 文件发送?您可以将其作为 CSV 文件获取吗?如果是这样,那么只需使用元数据编写程序来读取数据文件。比尝试编写程序来修复 XLSX 文件转换为数据集的方式要容易得多。
1赞 Reeza 2/18/2022
请改用 CALL EXECUTE 来动态执行语句。

答:

4赞 Tom 2/18/2022 #1

使用元数据编写代码。因此,如果您的元数据数据集名为 CODEBOOK,并且具有名为 FIELD_NAME 和 FIELD_LABEL 的变量,那么您可以编写如下的 LABEL 语句:

filename code temp;
data _null_; 
  set codebook end=eof;
  file code;
  if _n_=1 then put 'label';
  put @3 field_name '=' field_label :$quote. ;
  if eof then put ';' ;
end;

然后,可以使用 %INCLUDE 将该 label 语句添加到要运行它的位置。例如,作为 PROC DATASETS 步骤的一部分。因此,如果要添加标签的数据集在 MYLIB 库中称为 MYDATA,则运行此 PROC 步骤。

proc datasets lib=mylib nolist;
  modify mydata ;
%include code / source2;
  run;
quit;

您可以将类似的代码生成用于您可能想要进行的其他更改。

2赞 whymath 2/18/2022 #2

您在生成的变量中做得很好,该变量存储了可执行的 SAS 语句。现在,是时候让 SAS 解析变量内的表达式了。我命令你例行公事。Syntax_Labelcall execute()

call execute()解析参数,并发出已解决的值,以便在下一步边界执行。对你来说最重要的是,这个例程允许字符串或字符变量作为其参数。
让我们看一个例子。

data test;
  do gender='F','M';
    output;
  end;
run;

data _null_;
  set test;
  call execute(cat('
    data class_',gender,';
      set sashelp.class;
      where sex="',gender,'";
    run;
  '));
run;

通过运行此代码,SAS 将执行以下三项操作:

  1. 生成一个名为 test 的数据集,其中包含 2 行,变量性别的第一行是,第二行是FM;
  2. 在 中,SAS 解析 的参数,并将解析的结果存储在内存中,然后存储在 setp 上;data _null_call executedata _null_
  3. SAS 开始执行解析结果,即:
data class_F;
  set sashelp.class;
  where sex="F";
run;

data class_M;
  set sashelp.class;
  where sex="M";
run;

现在,您可以看到class_F和class_M的数据位于工作库中。
更令人惊讶的是,你可以有条件地使用,因为它是一个例程,这可能有助于你设计更复杂和灵活的程序。
call execute

至于你的问题,我认为你现在很容易得到以下解决方案:

data codebook_edit;
  set codebook end=eof;
  format Syntax_Label $2000.;
  Syntax_Label=cat(trim(Field_Name), " = '", trim(Field_Label), "'");

  if _n_=1 then call execute('data _null_; set codebook_edit; label ');
  call execute(Syntax_Label);
  if eof then call execute('; run;');
run;

我还将您的关键字移到了第一个以使代码干净。labelcall execute

评论

0赞 whymath 2/18/2022
如果您对“元编程”技能感兴趣,您可能还想知道该函数。dosubl
1赞 Reeza 2/18/2022 #3

完全是另一种方法。 不要生成多个标签语句,而是创建一个具有旧标签和新标签的数据集。将它们读入宏变量,然后应用它们。

*Create label data set;
data label_data_set;
length name label $25.;
name="Sex"; label="Gender"; output;
name="height"; label="Height (in)"; output;
name="weight"; label="Weight (lbs)"; output;
run;
 
 
*Create sample dataset to apply label;
data class;
set sashelp.class;
run;
 
 
*Create macro variable that holds label statement;
proc sql noprint;
select catx("=", name, quote(trim(label)))
  into :label_list separated by " "
from label_data_set;
quit;
 
 
*Display macro variable in log;
%put &label_list.;
 
 
*Apply labels without recreating dataset;
proc datasets library=work;
modify class;
label &label_list.;
run;quit;
 
 
*Print the dataset to display new labels;
proc print data=class label noobs;
run;

您可以使用类似的方法来重命名或应用格式。 使用 PROC DATASETS 应用这些比新的数据步骤更有效,因为它不会重新创建数据,只是更新元数据。