質問

2つの日付の間の「最も近い」月数に相当する数値を計算する必要があります。ただし、標準のSAS関数(INTCK)は、日付パラメーターのDAYを考慮するように調整されていません(たとえば、1に丸める必要がある場合、以下のコードは0に解決されます)。

この問題を解決する「最も近い」方法は何ですか?

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

編集:Martinsコメントへの応答。

0か月に丸めます-国境は関係ないと思います。複製しようとしている関数(NEAREST_MONTHS)はDCS(Sungard預言者アプリケーション)から来ています。日付の処理方法についてさらに理解するために、アプリケーション自体でいくつかのテストを実行する機会を待っています(ここに結果を投稿します)。

ヘルプファイルには以下が含まれます。 カテゴリー 日付

説明

2つの日付の差を最も近い月数に戻します。 2番目の日付が最初の日付より遅い場合、0が返されます。

構文

NEAREST_MONTHS(Later_Date、Earlier_Date)

戻りタイプ 整数

NEAREST_MONTHS(date1、date2) date1が20/3/1997でdate2が23/7/1996の場合8を返します

NEAREST_MONTHS(date1、date2) date1が20/3/1997でdate2が1/2/1995の場合、26を返します

役に立ちましたか?

解決

これは、DCSアプリケーションと同じ方法で計算すると思われる関数として作成しました。バージョン9.2のSASで新しく追加されたいくつかの機能を使用します。これには、日付の連続配置が含まれます。また、時間的に前後に動作します(つまり、early_dateがlater_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;

また、期間内の完全な月(「最初の1日から最後の1日」まで)を数えるアプローチを取り、残りの日を合計して、合計が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;

最初の方法は理解と保守が簡単ですが、2番目の方法は大きな間隔でより正確です(01FEB06から01FEB09は36か月ですが、方法1では35か月であることがわかります)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top