[英]SAS: How can I filter for (multiple) entries which are closest to the last day of month (for each month)
[英]How can I select the first and last week of each month in SAS?
我有每月的數據,每天有幾次觀察。 我有日,月和年變量。 如何僅保留每月前5天和最后5天的數據? 我的數據中只有工作日,因此該月的前五天和最后五天會逐月變化,例如,對於2008年1月,前五天可以是該月的第二,第三,第四,第七和第八天。 以下是數據文件的示例。 我不確定如何共享此內容,因此我只復制了以下幾行。 這是從2008年1月2日開始。first.variable和last.variable工作會有所變化嗎? 如何保留每個月的前5天和后5天的觀察結果? 謝謝。
1 AA 500 B 36.9800 NH 2 1 2008 9:10:21
2 AA 500 S 36.4500 NN 2 1 2008 9:30:41
3 AA 100 B 36.4700 NH 2 1 2008 9:30:43
4 AA 100 B 36.4700 NH 2 1 2008 9:30:48
5 AA 50 S 36.4500 NN 2 1 2008 9:30:49
如果要檢查數據並確定最小值5和最大值5,則可以使用PROC SUMMARY
。 然后,您可以將結果與數據合並回去以選擇記錄。
因此,如果您的數據包含變量YEAR,MONTH和DAY,則可以使用簡單的步驟創建一個新的數據集,該數據集具有每月的前五天和后五天。
proc sort data=HAVE (keep=year month day) nodupkey
out=ALLDAYS;
by year month day;
run;
proc summary data=ALLDAYS nway;
class year month;
output out=MIDDLE
idgroup(min(day) out[5](day)=min_day)
idgroup(max(day) out[5](day)=max_day)
/ autoname ;
run;
proc transpose data=MIDDLE out=DAYS (rename=(col1=day));
by year month;
var min_day: max_day: ;
run;
proc sql ;
create table WANT as
select a.*
from HAVE a
inner join DAYS b
on a.year=b.year and a.month=b.month and a.day = b.day
;
quit;
/****
get some dates to play with
****/
data dates(keep=i thisdate);
offset = input('01Jan2015',DATE9.);
do i=1 to 100;
thisdate = offset + round(599*ranuni(1)+1); *** within 600 days from offset;
output;
end;
format thisdate date9.;
run;
/****
BTW: intnx('month',thisdate,1)-1 = first day of next month. Deduct 1 to get the last day
of the current month.
intnx('month',thisdate,0,"BEGINNING") = first day of the current month
****/
proc sql;
create table first5_last5 AS
SELECT
*
FROM
dates /* replace with name of your data set */
WHERE
/* replace all occurences of 'thisdate' with name of your date variable */
( intnx('month',thisdate,1)-5 <= thisdate <= intnx('month',thisdate,1)-1 )
OR
( intnx('month',thisdate,0,"BEGINNING") <= thisdate <= intnx('month',thisdate,0,"BEGINNING")+4 )
ORDER BY
thisdate;
quit;
創建具有所需結構的數據 ;
Data inData (drop=_:); * froget all variables starting with an underscore*;
format date yymmdd10. time time8.;
_instant = datetime();
do _i = 1 to 1E5;
date = datepart(_instant);
time = timepart(_instant);
yy = year(date);
mm = month(date);
dd = day(date);
*just some more random data*;
letter = byte(rank('a') +floor(rand('uniform', 0, 26)));
*select week days*;
if weekday(date) in (2,3,4,5,6) then output;
_instant = _instant + 1E5*rand('exponential');
end;
run;
計算每月的天數 ;
proc sql;
create view dayCounts as
select yy, mm, count(distinct dd) as _countInMonth
from inData
group by yy, mm;
quit;
選擇日子 ;
data first_5(drop=_:) last_5(drop=_:);
merge inData dayCounts;
by yy mm;
_newDay = dif(date) ne 0;
retain _nrInMonth;
if first.mm then _nrInMonth = 1;
else if _newDay then _nrInMonth + 1;
if _nrInMonth le 5 then output first_5;
if _nrInMonth gt _countInMonth - 5 then output last_5;
run;
使用INTNX()
函數。 您可以使用INTNX('month',...)
查找INTNX('month',...)
的開始和結束日期,然后使用INTNX('weekday',...)
查找前5個工作日和最后5個工作日。
您可以使用MDY()
函數將月,日,年的值轉換為日期。 假設您這樣做並創建了一個名為TODAY
的變量。 然后要測試它是否在該月的最后5個工作日的前5個工作日內,您可以執行以下操作:
first5 = intnx('weekday',intnx('month',today,0,'B'),0) <= today
<= intnx('weekday',intnx('month',today,0,'B'),4) ;
last5 = intnx('weekday',intnx('month',today,0,'E'),-4) <= today
<= intnx('weekday',intnx('month',today,0,'E'),0) ;
請注意,這些范圍將包括周末,但是如果您的數據中沒有這些日期,則沒有關系。 但是,如果您的數據跳過假期,您可能會遇到問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.