繁体   English   中英

如何在 SAS 中循环变量格式和重命名

[英]How to Loop Through Variable Formats and Rename In SAS

我有一个数据集,其中每列代表从 2018 年 2 月到 2025 年 12 月的不同月份、年份组合。这些列存储为字符,但我想将它们转换为数字。 目前,这些列被命名为“FEB_18”、“MAR_18”、“NOV_19”、“JUL_22”等。

我想创建一个循环,获取每个变量并将其转换为数字。 最初,我使用了以下代码,但这会为每次迭代创建一个新数据集。

 %let months = JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC;

 %MACRO DOIT(Peak=); 

    %do i= 1 %to %sysfunc(countw(&Name.));
    %let Name2 = %scan(&months., &i.);
    %do j = 18 %to 25; 

proc sql;
    create table ppl as 
        select
        input(Label, Best12.) - 21916 as Contract format MMDDYY10., /* Excel to SAS Dates*/
        input(&Name2._&j., Best12.) as _&Name2._&j.
    from Transposed_&Peak.;
    %end;
    %end;
quit;


%mend DOIT; 
%DOIT(Peak = On);

提前致谢!

CONTENTS过程将使数据集的元数据(列名、类型、列号等)可用作数据。 从该数据中,您可以构建执行转换所需的语句

例子:

X_feb_20 = input(feb_20, ?? best12.);  * parse value in character variable into a numeric variable;
drop feb_20;  * drop character variable from output data set;
rename x_feb_20 = feb_20;  * change the name of the numeric variable back to the orginal;

因此,繁琐的工作是为数据集中所有名称代表<mon>_<yy>字符列执行该模式。 考试

input('01'||transtrn(name,'_','20'),anydtdte.) is not null 

将识别这样的列名。

这是一个将执行杂务的示例宏:

/* 
 * Fake some data to play with 
 */

%macro month_columns(from_month=, to_month=);

  %local index mon yy frstdate lastdate;

  %let frstdate = %sysevalf("01&from_month"D);
  %let lastdate = %sysevalf("01&to_month"D);

  %do date = %sysevalf("01&from_month"D) %to %sysevalf("01&to_month"D);
    %let date = %sysfunc(INTNX(MONTH,&date,0,E));

    %sysfunc(putn(&date,MONNAME3))_%sysfunc(putn(&date,YEAR2.))
  %end;

%mend;

data have;
  call streaminit(123);
  do stockid = 1 to 10;
    array futures $12 %month_columns(from_month=FEB2020, to_month=DEC2025);
    do over futures;
      futures = put(rand('uniform',50) + stockid * sin(_i_/40), 12.5);
    end;
    output;
  end;
run;

/* 
 * Chore macro
 */

%macro asnum_mon_yy_columns(data=, out=);

  %local index;

  proc contents noprint data=&data out=have_columns(keep=varnum name type);
  run;

  * SQLOBS will be number of rows (and thus names) that meet the date-like criteria ;

  proc sql noprint;
    select name into :name1-
    from have_columns
    where input('01'||transtrn(name,'_','20'),anydtdte.) is not null 
      and type = 2
    order by varnum
    ;
  quit;

  data &out;
    set &data;

    %do index = 1 %to &sqlobs;
      X_&&name&index = input(&&name&index,??best12.);
    %end;

    %if &sqlobs %then %do;
      drop   %do index = 1 %to &sqlobs;
                &&name&index
             %end;
      ;
      rename %do index = 1 %to &sqlobs;
                X_&&name&index = &&name&index
             %end;
      ;
    %end;
  run;

%mend;

/*
 * Invoke chore
 */

options mprint;

%asnum_mon_yy_columns(data=have, out=want)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM