简体   繁体   English

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

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

I have a dataset where each column represents a different month, year combination from February 2018 to December 2025. These columns are stored as characters, but I would like to convert them to numeric.我有一个数据集,其中每列代表从 2018 年 2 月到 2025 年 12 月的不同月份、年份组合。这些列存储为字符,但我想将它们转换为数字。 Currently, the columns are named 'FEB_18', 'MAR_18', 'NOV_19', 'JUL_22' ect.目前,这些列被命名为“FEB_18”、“MAR_18”、“NOV_19”、“JUL_22”等。

I would like to create a loop takes each variable and converts it to numeric.我想创建一个循环,获取每个变量并将其转换为数字。 Originally, I used the following code, but this creates a new dataset for each iteration.最初,我使用了以下代码,但这会为每次迭代创建一个新数据集。

 %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);

Thanks in advance!提前致谢!

The CONTENTS procedure will make the metadata (column names, types, column number,etc) of the data set available as data. CONTENTS过程将使数据集的元数据(列名、类型、列号等)可用作数据。 From that data you can construct the statements needed to perform the conversion从该数据中,您可以构建执行转换所需的语句

Example:例子:

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;

So the chore is to do that pattern for all character columns in the data set whose name represents a <mon>_<yy> .因此,繁琐的工作是为数据集中所有名称代表<mon>_<yy>字符列执行该模式。 The test考试

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

will identify such column names.将识别这样的列名。

Here is an example macro that will perform the chores:这是一个将执行杂务的示例宏:

/* 
 * 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