簡體   English   中英

如何在SAS中選擇​​每月的第一周和最后一周?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM