SAS 年份函数在宏内部不起作用

SAS year function not working inside macro

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

%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

基本问题是 YEAR() 函数 returns 一个 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 

要将日期值转换为年份,您可以使用 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));