我想有一个二进制标志矩阵,表明假日是否在某一天发生,类似这样(但每次SAS认可的假期):
date flag_BOXING flag_CHRISTMAS flag_... flag_...
14DEC2014 0 0 0 0
15DEC2014 0 0 0 0
16DEC2014 0 0 0 0
17DEC2014 0 0 0 0
18DEC2014 0 0 0 0
19DEC2014 0 0 0 0
20DEC2014 0 0 0 0
21DEC2014 0 0 0 0
22DEC2014 0 0 0 0
23DEC2014 0 0 0 0
24DEC2014 0 0 0 0
25DEC2014 0 1 0 0
26DEC2014 1 0 0 0
27DEC2014 0 0 0 0
28DEC2014 0 0 0 0
我知道可能有一种更简单的方法可以做到这一点,但是在我继续我目前的尝试(实际上并没有工作......)之前要确定。我想创建一个单独的列来引入实际假期的日期,然后如果该日期与特定行上的日期匹配,则标志变量变为1.这样做的缺点是我必须这样做每个假期。此外,假日功能需要一年的规格,所以我将不得不使用一些if-elseif逻辑来计算不同的年份(我的列表是几年的日期)。是否有一种简单的方法来生产我想要的矩阵,或者这是最好的方法吗?
data test;
length day $9;
input day $;
cards;
23DEC2014
24DEC2014
25DEC2014
26DEC2014
27DEC2014
28DEC2014
;
run;
data test(drop=BOXING CHRISTMAS);
set test;
BOXING=holiday('boxing', 2014);
CHRISTMAS=holiday('christmas', 2014);
format BOXING CHRISTMAS date9.;
flag_BOXING=0;
flag_CHRISTMAS=0;
if upcase(day)=upcase(BOXING) then flag_BOXING=1;
if upcase(day)=upcase(CHRISTMAS) then flag_CHRISTMAS=1;
run;
感谢。
答案 0 :(得分:3)
这是一种蛮力方法。如果您只需要特定日期,我会这样做,然后以某种方式合并/过滤结果。请注意,数组需要对齐,假日名称和标志变量才能生效。 h_list是感兴趣的假日列表,存储为临时数组,不输出到最终数据集。
data want;
format date date9.;
array h_list(6) $12. _temporary_ ("newyear" "thanksgiving", "christmas", "easter", "mlk", "memorial");
array h_flag(6) flag_newyear flag_thanksgiving flag_christmas flag_easter flag_mlk flag_memorial;
date_start="01Jan2013"d;
date_end="31Dec2015"d;
do date=date_start to date_end;
year=year(date);
do i=1 to dim(h_list);
h_flag(i)=0;
if date=holiday(h_list(i), year) then h_flag(i)=1;
end;
output;
end;
run;
答案 1 :(得分:3)
我们有一个宏可以做到这一点。只需指定您要为其计算假期的日期范围,它就会显示一个表,每个假日有一行。
%holidays(iStartDt=%sysfunc(mdy(1,1,2007)), iEndDt=%sysfunc(today())+100);
您可以获取它创建的数据集并加入现有数据以获取所需的字段。
这是宏:
/*****************************************************************************
** PROGRAM: MACROS.HOLIDAYS.SAS
**
** CREATES A DATASET CONTAINING A LIST OF PUBLIC HOLIDAYS
**
** PARAMETERS:
**
******************************************************************************
** HISTORY:
** 1.0 MODIFIED: 30-JUN-2010 BY:RP
** - CREATED.
*****************************************************************************/
%macro holidays(iStartDt=, iEndDt=);
data holidays;
attrib holiday_date format=date9.
holiday_desc length=$30
rule length=$30
;
yr_start = year(&iStartDt);
yr_end = year(&iEndDt);
do yr_tmp=yr_start to yr_end;
holiday_date = mdy(1,1,yr_tmp);
holiday_desc = "New Years Day";
rule = "";
output;
holiday_date = mdy(7,4,yr_tmp);
holiday_desc = "July 4th";
rule = "";
output;
holiday_date = mdy(11,11,yr_tmp);
holiday_desc = "Veterans Day";
rule = "November 11";
output;
holiday_date = mdy(12,25,yr_tmp);
holiday_desc = "Christmas Day";
rule = "";
output;
**
** Martin Luther King Day [3rd monday in Jan]
*;
cnt = 0;
do tmp_date = mdy(1,1,yr_tmp) to mdy(2,1,yr_tmp);
if weekday(tmp_date) eq 2 then do;
cnt = cnt + 1;
if cnt = 3 then do;
leave;
end;
end;
end;
holiday_date = tmp_date;
holiday_desc = "MLK Day";
rule = "3rd Monday in Jan";
output;
**
** Presidents Day [3rd monday in Feb]
*;
cnt = 0;
do tmp_date = mdy(2,1,yr_tmp) to mdy(3,1,yr_tmp);
if weekday(tmp_date) eq 2 then do;
cnt = cnt + 1;
if cnt = 3 then do;
leave;
end;
end;
end;
holiday_date = tmp_date;
holiday_desc = "Presidents Day";
rule = "3rd Monday in Feb";
output;
**
** Memorial Day [last monday in May]
*;
cnt = 0;
do tmp_date = mdy(6,1,yr_tmp)-1 to mdy(5,1,yr_tmp) by -1;
if weekday(tmp_date) eq 2 then do;
cnt = cnt + 1;
if cnt = 1 then do;
leave;
end;
end;
end;
holiday_date = tmp_date;
holiday_desc = "Memorial Day";
rule = "Last monday in May";
output;
**
** Labor Day [1st monday in Sept]
*;
cnt = 0;
do tmp_date = mdy(9,1,yr_tmp) to mdy(10,1,yr_tmp);
if weekday(tmp_date) eq 2 then do;
cnt = cnt + 1;
if cnt = 1 then do;
leave;
end;
end;
end;
holiday_date = tmp_date;
holiday_desc = "Labor Day";
rule = "1st monday in Sept";
output;
**
** Columbus Day [2nd monday in Oct]
*;
cnt = 0;
do tmp_date = mdy(10,1,yr_tmp) to mdy(11,1,yr_tmp);
if weekday(tmp_date) eq 2 then do;
cnt = cnt + 1;
if cnt = 2 then do;
leave;
end;
end;
end;
holiday_date = tmp_date;
holiday_desc = "Columbus Day";
rule = "2nd monday in Oct";
output;
**
** Thanksgiving Day [4th thursday in Nov]
*;
cnt = 0;
do tmp_date = mdy(11,1,yr_tmp) to mdy(12,1,yr_tmp);
if weekday(tmp_date) eq 5 then do;
cnt = cnt + 1;
if cnt = 4 then do;
leave;
end;
end;
end;
holiday_date = tmp_date;
holiday_desc = "Thanksgiving Day";
rule = "4th thursday in Nov";
output;
end;
keep holiday_date holiday_desc rule;
run;
proc sort data=holidays(where=(holiday_date between &iStartDt and &iEndDt));
by holiday_date;
run;
**
** WHEN A HOLIDAY FALLS ON A NONWORKDAY -- SATURDAY OR SUNDAY -- THE HOLIDAY USUALLY IS OBSERVED
** ON MONDAY (IF THE HOLIDAY FALLS ON SUNDAY) OR FRIDAY (IF THE HOLIDAY FALLS ON SATURDAY).
*;
data holidays;
format adjusted_date date9.;
length adjusted_downame downame $15;
set holidays;
downame = upcase(cats(put(holiday_date, downame.)));
if downame eq ("SATURDAY") then do;
adjusted_date = holiday_date - 1;
end;
else if downame eq ("SUNDAY") then do;
adjusted_date = holiday_date + 1;
end;
else do;
adjusted_date = holiday_date;
end;
adjusted_downame = upcase(cats(put(adjusted_date, downame.)));
run;
%mend;