SAS年度功能在宏

时间:2016-12-21 12:23:55

标签: sas sas-macro

您好我正在尝试使用特定日期格式从库中访问列,并在我的宏代码中的列上使用年份函数,但它会生成重复值...但是年份函数显示重复值并且不提供所需结果。我的代码应该只返回输入日期的年份。

%macro dteyear(lib=,outdsn=);
proc sql noprint;
select distinct catx(".",libname,memname), name 
into :dsns separated by " ", :varname separated by " "
from dictionary.columns
where libname = upcase("&lib") and format=('YYMMDD10.')
order by 1;
quit;
%put &dsns;
%put &varname;
%local olddsn curdsn curvbl i;
data &outdsn.;
set 
%let olddsn=;
%do i=1 %to &sqlobs;
%let curdsn=%scan(&dsns,&i,%str( ));
%let curvbl=%scan(&varname,&i,%str( ));
%if &curdsn NE &olddsn
%then %do;
%if &olddsn NE
%then %do;
)
%end;
%let olddsn=&curdsn.;
&curdsn (keep=&curvbl
%end;
%else %do;
&curvbl
%end;
%end;
);
%do i=1 %to &sqlobs;
%scan(&varname,&i,%str( ))=year(&varname.);
%end;
run;
proc print data=&outdsn;run;
%MEND;
%dteyear(lib=dte3,outdsn=dtetst);


the input data is as follows
1975-12-04 
1977-11-03
1989-09-15
1998-06-17
1999-05-31
2000-08-14
2001-03-11
2007-03-11
2007-12-28
2008-10-07
2009-12-03

我的代码的重复输出是 - >

Obs RFDTC 
1 1965-05-19 
2 1965-05-19 
3 1965-05-19 
4 1965-05-19
5 1965-05-19
6 1965-05-19
7 1965-05-19
8 1965-05-19
9 1965-05-19
10 1965-05-19
11 1965-05-19
12 1965-05-19
13 1965-05-19

2 个答案:

答案 0 :(得分:0)

基本问题是YEAR()函数返回一个4位数字,变量格式为YYMMDD10。所以结果格式化为非常接近1960的SAS日期(SAS的所有时间开头)

我在下面的代码中所做的是将格式更改为4.0,因此它显示为4位数字。

如果您想要访问原始日期变量,则必须为该年创建一个新变量。我会留给你的。

还有一个问题 - 也就是说,YEAR(&varname.)会插入整个变量列表,而不仅仅是您正在使用的变量列表。如果只有一个日期变量,它可以工作,但如果有多个日期变量则不行。我也解决了这个问题。

%macro dteyear(lib=,outdsn=);
proc sql noprint;
select distinct catx(".",libname,memname), name 
into :dsns separated by " ", :varname separated by " "
from dictionary.columns
where libname = upcase("&lib") and format=('YYMMDD10.')
order by 1;
quit;
%put &dsns;
%put &varname;
%local olddsn curdsn curvbl i;
data &outdsn.;
set 
%let olddsn=;
%do i=1 %to &sqlobs;
%let curdsn=%scan(&dsns,&i,%str( ));
%let curvbl=%scan(&varname,&i,%str( ));
%if &curdsn NE &olddsn
%then %do;
%if &olddsn NE
%then %do;
)
%end;
%let olddsn=&curdsn.;
&curdsn (keep=&curvbl
%end;
%else %do;
&curvbl
%end;
%end;
);
%do i=1 %to &sqlobs;
%let curvbl=%scan(&varname,&i,%str( ));
&curvbl=year(&curvbl.);
format &curvbl 4.0;
%end;
run;
proc print data=&outdsn;run;
%MEND;

data have;
    input datevar yymmdd10.;
    format datevar yymmdd10.;
cards;
1975-12-04 
1977-11-03
1989-09-15
1998-06-17
1999-05-31
2000-08-14
2001-03-11
2007-03-11
2007-12-28
2008-10-07
2009-12-03
run;

options mprint;

%dteyear(lib=work,outdsn=want)

结果是:

Obs datevar 
1 1975 
2 1977 
3 1989 
4 1998 
5 1999 
6 2000 
7 2001 
8 2007 
9 2007 
10 2008 
11 2009 

答案 1 :(得分:0)

要将日期值转换为一年只能使用YEAR()函数,但您还需要更改附加到变量的格式,因为您将基本上将存储在其中的值除以365以将其转换为到这个年数的天数。

rfdtc = year(rfdtc);
format rfdtc 4. ;

您的宏正在尝试从许多数据集中读取许多变量并生成单个输出数据集。我不确定结果数据集对您有多大价值,因为它看起来像缺失值的检查板。此外,如果相同的变量名称出现在多个输入数据集中,则会因为将YEAR()函数应用于已从日期值转换为年份值的值而获得损坏的值。

例如,您最终可能会生成如下数据步骤:

data WANT ;
  set ds1 (keep=datevar1)
      ds1 (keep=datevar2)
      ds2 (keep=datevar3)
      ds3 (keep=datevar3)
  ;
  datevar1=year(datevar1);
  datevar2=year(datevar2);
  datevar3=year(datevar3);
  datevar3=year(datevar3);
  format datevar1 datevar2 datevar3 datevar3 4.;
run;

由于输入数据集DS2和DS3都有一个名为DATEVAR3的变量,因此您将YEAR()函数应用于该值两次。这将把所有东西都转换为1965年。

为了消除多次在相同值上运行YEAR()函数并丢失实际年份的问题,您可能只想应用YEAR.格式而不是转换存储的值。

 format datevar1 datevar2 datevar3 datevar4 year. ;

那仍然会留下潜在的不同日期值。如果你真的需要值相同或许你可以将值转换为一年的第一天?您可以使用INTNX()功能

 datevar1 = intnx('year',datevar1,0,'b');

MDY()函数

 datevar1 = mdy(1,1,year(datevar1));