문제

두 날짜 사이의 '가장 가까운'달과 동일 한 그림을 계산해야합니다. 그러나 표준 SAS 함수 (INTCK)는 날짜 매개 변수의 날을 고려할 수 있도록 준비되어 있지 않습니다 (예를 들어 아래 코드는 1로 반올림 할 때 0으로 해결).

이 문제를 해결하는 '가장 깔끔한'방법은 무엇입니까?

data _null_;
    x="01APR08"d;
    y="28APR08"d;
    z=intck('MONTH',x,y);
    put z= ;
run;

편집 : Martins 의견에 대한 응답.

나는 0 개월에서 반올림 할 것입니다 - 국경이 관련이 있다고 생각하지 않습니다. 복제하려는 기능 (가장 가까운 _months)은 DCS (Sungard Prophet Application)에서 나옵니다. 이제 응용 프로그램 자체 내에서 일부 테스트를 수행하여 날짜를 취급하는 방법에 대해 더 많이 이해할 수있는 기회를 기다리고 있습니다 (여기에 결과를 게시 할 것임).

도움말 파일에는 다음이 포함되어 있습니다. 카테고리 날짜

설명

두 날짜의 차이를 가장 가까운 달에 반환합니다. 두 번째 날짜가 첫 번째 날짜보다 늦으면 0이 반환됩니다.

통사론

가장 가까운 _months (ageer_date, reconer_date)

리턴 유형 정수

가장 가까운 _months (date1, date2)는 날짜 1이 1997 년 20/3/1997이고 Date2는 1996 년 23/7/1996 인 경우 8 반환 8

가장 가까운 _months (date1, date2)는 Date1이 1997 년 20/3/1997이고 Date2는 1995 년 1/2/1995 인 경우 26을 반환합니다.

도움이 되었습니까?

해결책

나는 이것을 DCS 응용 프로그램과 같은 방식으로 계산한다고 생각하는 함수로 썼습니다. 버전 9.2의 SAS에 새로운 기능을 사용하여 날짜의 연속 정렬을 포함하여 일부 기능을 사용합니다. 또한 시간에 앞으로 또는 뒤로 작동합니다 (예 : early_date가 나중에 _date 이후에 부정적인 정수를 제공합니다). 나는 다음 달까지 컷오프로 간격을 넘어 15 일 이상을 사용했지만 원하는 경우 조정할 수 있습니다.

proc fcmp outlib=work.myfuncs.dates;
   function nearest_months(later_date,earlier_date);
        /* Return missing if inputs are missing */
        if (earlier_date eq . ) OR (later_date eq . ) then
            nearest_month=.;
        else do; 
            /* Use 'cont' argument for continuous dates */
            months=intck('MONTH',earlier_date,later_date,'cont');
            if months < 0 then months=months+1;
            days= later_date - intnx('month', earlier_date,months,'same');

            /* Handle negatives (earlier dates) */
            if months < 0 then do;
                if days < -15 then months=months-1;
                nearest_month=months;
                end;
            else do;
                if days > 15 then months + 1;
                nearest_month=months;
                end;
        end;
        return(nearest_month);
   endsub;
run;
options cmplib=work.myfuncs;


data _null_;
x=nearest_months('20Mar1997'd, '23JUL1996'd);
put x=;
x=nearest_months('20Mar1997'd, '01FEB1995'd);
put x=;
run;

이것은 당신의 참조와 동일합니다.

x=8
x=26

다른 팁

당신은 사용할 수 있습니다 INTNX 반올림인지 아래로 내려야하는지 확인하려면


data _null_;
  format x y date9. z 8.;
  x="01APR08"d;
  y="28APR08"d;
  z=intck('MONTH',x,y);

  * wl is x + z months;
  wl=intnx('MONTH',x,z);

  * wu is x + (z+1) months;
  wu=intnx('MONTH',x,z+1);

  * If y is closer to wu, then adjust z by 1;
  if (abs(y-wu) lt abs(y-wl)) then z = z+1;     

  put x y z=;
run;

한 달을 30 일로 정의하는 경우 15 일 이하의 0 개월 이하, 16 일 이상 최대 1 개월입니다. 이것은 다음과 같이 달성 할 수 있습니다.

data _null_;
  format x y date9. z 8.;
  x="14FEB09"d;
  y="02MAR09"d;

  z=round(intck('DAY',x,y)/31);
  put x y z=;
run;

또한 간격으로 몇 달 동안 ( "첫 번째 ~ 마지막 1st")를 계산하기 위해 접근 한 다음 남은 날을 추가하여 최대 0, 1 또는 2 개월을 합산하는지 확인할 수 있습니다. 이와 같이:

data _null_;
  format x y date9. z 8.;
  x="01FEB09"d;
  y="31MAR09"d;

  if day(x)=1 then do;
     z=intck('MONTH',x,intnx('MONTH',y,0,'BEGINNING'))
         + round((intck('DAY',intnx('MONTH',y,0,'BEGINNING'),y))/31);
  end;
  else do;
     z=intck('MONTH',intnx('MONTH',x,1,'BEGINNING'),intnx('MONTH',y,0,'BEGINNING'))
         + round((intck('DAY',x,intnx('MONTH',x,1,'BEGINNING'))+intck('DAY',intnx('MONTH',y,0,'BEGINNING'),y))/31);
  end;
  put x y z=;
run;

첫 번째 방법은 이해하고 유지하기가 더 쉽지만 두 번째 방법은 큰 간격에 대해 더 정확합니다 (01Feb06 ~ 01Feb09는 36 개월이지만 방법 1은 35에 불과합니다).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top