読者です 読者をやめる 読者になる 読者になる

「データフレームの時間列を文字列分解して、日付と時間にして、それぞれ別の列にして追加したい。でも、strsplit関数を使うとリストで返ってきて困る」 時の対処法

解決策

sapplyと自作関数の併用で乗り切る


いまこんなデータがあるとする

> print(head(ex_data))
             date_jst ID
1 2014-05-11 00:00:04   17220
2 2014-05-11 00:00:05   25377
3 2014-05-11 00:00:05   21841
4 2014-05-11 00:00:06   23536
5 2014-05-11 00:00:07   18980
6 2014-05-11 00:00:09   25355

で、日付と時間は別々の列に格納して扱いたい時が、ある(はず)

でも、文字分解のstrsplit関数は

day_time_jst <- as.character(ex_data[,1])
> str_list <- strsplit(day_time_jst, split=" ")
> print(class(str_list))
[1] "list"

リストで返してくるもんだから、そのまんまでは困る。

で、そこでsapplyを使う。

sapplyはリストを入力にして、ベクトルを出力にして、再起的に実行してくれる。

なので、dayとtimeを取り出す関数を自分で定義して、sapplyで呼び出してやればよい。

定義する関数は以下の通り。

MyFunc <- function(input_vec){
  print(class(input_vec))
  print(input_vec[1])
  day <- input_vec[1]
  time <- input_vec[2]
  
  return(c(day, time))
}

これをsapplyで呼び出すと

a <- sapply(str_list, MyFunc)

[1] "character"
[1] "2014-05-11"
[1] "character"
[1] "2014-05-11"

自作関数に渡される場面ではすでにベクトルに変換されていることがわかる。

なので、関数内ではベクトルのインデックス指定を使って、要素を取り出すことができる。

実行例

> a
     [,1]         [,2]         [,3]         [,4]         [,5]         [,6]         [,7]         [,8]         [,9]         [,10]       
[1,] "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11"
[2,] "00:00:04"   "00:00:05"   "00:00:05"   "00:00:06"   "00:00:07"   "00:00:09"   "00:00:10"   "00:00:10"   "00:00:12"   "00:00:12"  
     [,11]        [,12]        [,13]        [,14]        [,15]        [,16]        [,17]        [,18]        [,19]        [,20]       
[1,] "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11" "2014-05-11"
[2,] "00:00:12"   "00:00:45"   "00:00:45"   "00:00:45"   "00:00:45"   "00:00:47"   "00:00:47"   "00:00:48"   "00:00:50"   "00:00:52"  

なんかmatrix型になって返ってきちゃいましたけど・・・・ ま、でも、関数を

MyFunc <- function(input_vec){
  print(class(input_vec))
  print(input_vec[1])
  day <- input_vec[1]
  time <- input_vec[2]
  
  return(day)
}

にすれば、ちゃんとdayの要素だけは取得できるので、OKってことで。