Stataの日付と時刻をマスターする

プログラミング

このブログでは、統計解析ソフトStataのプログラミングのTipsや便利コマンドを紹介しています.

Facebook groupでは、ちょっとした疑問や気づいたことなどを共有して貰うフォーラムになっています. ブログと合わせて個人の学習に役立てて貰えれば幸いです.

さて今日は日付・時刻の取り扱いについて解説してみたいと思います.Stataで日付関連で困ることベスト5(集計n=1)としては、

  1. 文字列で入ってしまった!日数計算できないじゃん!
  2. 日付情報をnumericにしたら訳のわからない数字に変換された!
  3. 打ち切り日を入れようとしたらnumericにしたあとだと無理だった!
  4. 時刻入りの日付がnumericに変換できない!
  5. 時刻入りの日付とタダの日付との間で日数を計算できない!

こんなところかなと思います.そんな「困った!」に対応するようなまとめが日本語で存在しなかったので、自分で作ってみることにしました.

恐らく今回の記事を読むと日付に関する悩み事の8割くらいは解決するのではないかと思います.

1.Stringからnumericへの変換

最初の難関は、取り込んだデータの日付が文字列だったときに訪れます.サンプルデータをもとに考えてみましょう.

input id str16 birthdts str16 startdts str20 eventdatetime
1 "1985/05/03" "2019/05/01" "2020/06/30 19:10:15"
2 "1991/06/16" "2019/06/11" "2020/10/10 07:25:34"
3 "1972/11/29" "2019/04/21" "2020/09/04 03:38:52"
4 "1989/01/04" "2019/10/01" "2020/11/19 08:42:25"
5 "1980/12/17" "2019/12/11" "2020/12/28 11:23:42"
 end
list id birthdts startdts eventdatetime

誕生日、研究開始日、イベント発生日時といった感じで入力してみました.

まずは文字列である日付をnumericに変換します.ここでは日付変換のためのdate関数を使って新しい変数のbirthdtnを作成します.そのあとで変数の表示方法を日月年に表示してみます.

generate birthdtn = date(birthdts, "YMD") 
format birthdtn %td
list id birthdts startdts eventdatetime birthdtn

YMDの順でない場合、例えばDMYやMDYなら””の中をそのような順番にするだけでOKです.

さて、イベントの日付(eventdatetime)は時間の情報も含んでいます.このときは”clock”という関数を使って分解していきます.先ほどのdate関数では年月日ということで”YMD”を組み込みましたが、今度の変数は時間分秒まで入っています。

そういった場合には”YMDhms”とします.秒がなければ”YMDhm”まででよいわけです.numericにしたあとはformatするのですが、今回は%tcとしてみましょう.

generate eventdtn = clock(eventdatetime, "YMDhms") 
format birthdtn %tc
list id birthdts startdts eventdatetime eventdtn

こんな感じで表示されるようになります.formatによる表示方法をまとめるとこんな感じになりました.

numericになった日付情報は計算をしたりするのに便利ですので、まずはこの技を押さえておきましょう.

2.numeric日付・時刻から特定の要素を取り出す

numericの日付情報から年、月、日のみ、あるいは時刻付き日付情報から日付情報のみを取り出す方法をご紹介します.

generate birthmon = month(birthdtn)
generate birthyear = year(birthdtn)
generate birthday = day(birthdtn)
generate birthdt2 = mdy(birthmon, birthday, birthyear)
format birthdt2 %td

これで年月日をそれぞれ取り出したり、あるいは結合し直すこともできます.

結合する順番はmdyのみであることは確認済みです(2020.8.1現在, Stata 16.1).

また、結合に際しては時刻もmdyhms関数、具体的にはmdyhms(月, 日, 年, 時, 分,秒)で結合してformatすればよいです.

このとき、変数の文字数が増えてしまうので、generate double として新しい変数を設定するようにしましょう.

他にもdhms, hmsという関数もあります.下の例で整理してみました.

clear
input year month day hour min sec
  2001  10  3  5  30  12
  2002  3  4   4  10  1
end

gen double datetime = mdyhms(month, day, year, hour, min, sec)

gen double time = hms(hour,min,sec)
gen double date = mdy(month,day,year)
gen double datetime2 = dhms(date, hh(time), mm(time), ss(time))

format datetime datetime2 %tcCCYY.NN.DD_HH:MM:SS

ひとつ目でmdyhms関数を使った場合のsyntaxを示しますが、一番単純ですね.

例えば日付はあるけど時間分秒は別々に格納されている、といった場合には、

まずhms関数で時間、mdy関数で日付をそれぞれ作り、dhms関数で結合する、という手順を踏みましょう.秒のデータがない、という場合には秒のところはとりあえず1とかに仮置きしてみるとよいでしょう.

formatについては前述の通りですネ.

さて、時刻付き日付をただの日付に換えるには、date of clockの略である”dofc”という名の関数が必要です.これがあれば研究開始日から何日目、あるいは何年目でイベントを起こしているかを計算することができます.

generate eventdate = dofc(eventdtn)
generate startdtn = date(startdts, "YMD") 
format eventdate startdtn %td
generate followupday = eventdate - startdtn
generate followupyear = (eventdate - startdtn)/365.25
list id birthdtn eventdtn eventdate startdtn followupday followupyear

なお、時刻つき日付ではday, month, yearのそれぞれの関数は使えません.dofc関数を一度かませてタダの日付に貶めてやらないといけないのです.

具体的には、day(dofc(eventdatetime)) という具体に関数in関数してあげればよいのです.

3.曜日や1年の中の何日目?を取り出す

Stataでは曜日、1年の中の何日目か、1年の中の何週目、四半期の何期目か、というのを知る関数がそれぞれ準備されています.

  • dow: 0=日, 1=月, 2=火, 3=水, 4=木, 5=金, 6=土
  • doy: 年の何日目か
  • week: 年の何週目か
  • quarter: 年の第何四半期か
generate birdow = dow(birthdtn)
generate birdoy = doy(birthdtn)
generate birweek = week(birthdtn)
generate birqtr = quarter(birthdtn)
list id birthdtn birdow birdoy birweek birqtr

これで1番目の人は金曜日生まれとわかりますね.3ヶ月ごとの最初の情報(処方、検査値、血圧、透析条件などなど)を使う、みたいな条件設定もこのquarterを使うとできます。欠損値がない最初のデータを日付でsortして一番上にでてきたものを使う、とすればよいことがわかります.

4.特定の日付を置く

打ち切り日を指定するとき、日付を直接入力したいのにうまくいかなかった経験はありませんか?numericだと日付固有の数値(具体的には1960/1/1からの数え日数が相当しますが)を入れないといけません.当然そんなものはすぐには計算できないですから、関数が必要になります.

ここで使う関数は”td”関数です.td(ddmonyyyy)といれれば数値化されます.

例えば,

generate toevent = eventdate - startdtn
generate tocensor = td(20dec2020) - startdtn
list id startdtn eventdtn toevent tocensor

イベントまでの日数と打ち切りまでの日数を比較できます.どちらか小さい方を採用する、などすれば正確なフォローアップ日数がわかります.

(どちらか小さい方ならmin関数を使えばいいことになります)

5.年月や四半期で表現したいとき

データセットによっては年月までしかない場合、月単位まででよいとき、あるいは四半期データのみでよいような状況があり得ます.

日付データを丸める場合は簡単で、すでに日付データになっている場合には、

  • qofd(日付変数)
  • mofd(日付変数)

といった関数を使って次のように新たな日付変数を作ることができます.

  • 2019q4 … 2019年の第4四半期
  • 2020m6 … 2020年の6月

こうした値は、表示がこのような数字と文字列の混合になっているように見えますが、数値データとして扱われます.

これらの関数を使って新しく変数(シリアル値)を作成したあとにformatでお望みの形式に表示させることができるようになります.

yearmonthという変数にしてYYYYmMMの形式で表示させたい場合には、

.format yearmonth %tm

とすればよいわけです.

なお、データセットの都合上、日付データが数値データでYYYYMMとなっている場合には、一工夫が要ります.

方法1.Stringにする場合

   ⇒ まず、YYYYMM01にする.

     さらにそれをdate関数で日付の連続データとし、上記関数を使う

tostring yearmonth, replace force
gen date1 = yearmonth + "01" 
gen date2 = date(date1, "YMD") 
gen mdate = mofd(date2)
format mdate %tm

方法2.Numericのままで扱う場合

   ⇒ ym関数を使って新しいシリアル値を作成する

gen mdate = ym(floor(yearmonth/100), mod(yearmonth, 100))
format mdate %tm

6.まとめ

今回でてきた関数をまとめると、

  • dateとclockでstring to numeric
  • month, day, yearで分解、mdyで合成
  • dofcでclock to date
  • dow, doy, week, quarterで相対的な位置を特定
  • 特定の日付を入れるのにtd関数

日付に関する必要で8割方のデータ処理をするのに十分な方法についてご紹介しました.もっと詳しく学びたい方は以下のStata Pressのdata managementの本が参考になります.このシリーズ、分厚いくせにまったく英語が難しくないのでとっても読みやすいです.オススメです!

コメント

タイトルとURLをコピーしました