2017-10-12 11 views
2

時系列データをグループごとに設定する方法を探していました。私が使用していた非常に非効率的な方法は、グループごとにデータセットをsplitに設定し、そのリストのすべての要素でカスタム時系列フィル関数を適用します(最大と最小の間のシーケンスを作成してマージします)。言うまでもなく、この操作は分割を通過しません。グループごとに時系列を効率的に入力する

私のデータセットが

source     grp cnt 
1:  83 2017-06-06 13:00:00 1 
2:  83 2017-06-06 23:00:00 1 
3:  83 2017-06-07 03:00:00 1 
4:  83 2017-06-07 07:00:00 2 
5:  83 2017-06-07 13:00:00 1 
6:  83 2017-06-07 19:00:00 1 
7:  83 2017-06-08 00:00:00 1 
8:  83 2017-06-08 14:00:00 1 
9:  83 2017-06-08 15:00:00 1 
10:  83 2017-06-08 20:00:00 1 
11: 137 2017-06-04 02:00:00 1 
12: 137 2017-06-04 05:00:00 1 
13: 137 2017-06-04 23:00:00 1 
... 

、のように見える私の試みは、およそ40〜45秒後、すなわち

library(tidyverse) 

d1 %>% 
group_by(source) %>% 
complete(source, grp = seq(min(grp), max(grp), by = 'hour')) 

しかし、complete機能を利用することによりtidyverseメソッドを使用していました、プログレスバーが表示された(明らかに、いくつかの整頓機能ではきれいな機能 - この場合はcompleteと思われる)完了するまでに9時間。私のデータセットは非常に大きく、これは最も軽い操作ではないので、本当に効率的なものが私が探しているものです。

DATA

#dput(d1) 
structure(list(source = c("83", "83", "83", "83", "83", "83", 
"83", "83", "83", "83", "137", "137", "137", "137", "137", "137", 
"137", "137", "137", "137", "137", "137", "137", "137"), grp = structure(c(1496743200, 
1496779200, 1496793600, 1496808000, 1496829600, 1496851200, 1496869200, 
1496919600, 1496923200, 1496941200, 1496530800, 1496541600, 1496606400, 
1496617200, 1496649600, 1496696400, 1496808000, 1496844000, 1496876400, 
1496962800, 1497880800, 1497888000, 1497978000, 1497996000), class = c("POSIXct", 
"POSIXt"), tzone = ""), cnt = c(1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L 
)), .Names = c("source", "grp", "cnt"), row.names = c(NA, -24L 
), class = "data.frame") 
+0

関連:[?data.frameに欠損値の行を追加するための最速の方法](https://stackoverflow.com/questions/10438969/fastest-way-to-add-rows-for-missing -value-in-a-data-frame/10473931#10473931) – Henrik

+0

@Henrikリンクありがとうございます。私は欠けている日付を記入することに関して多くのQを実際に行ったが、それらのいずれにもグループ化は必要なかった。 – Sotos

+1

また、[グループで不足している日付を記入](https://stackoverflow.com/a/31502628/1851712) – Henrik

答えて

3

data.tableが本当にtidyverseオプションよりもはるかに高速であることが表示されます。したがって、単に上記をdata.table(@Frankの賛辞)に翻訳するだけで、わずか3分で操作が完了しました。

library(data.table) 

mDT = setDT(d1)[, .(grp = seq(min(grp), max(grp), by = "hour")), by = source] 
new_D <- d1[mDT, on = names(mDT)] 

new_D <- new_D[, cnt := replace(cnt, is.na(cnt), 0)] #If needed 
1

これは動物園を使用して行うこともできます。これは問題のコードとデータよりもはるかに高速ですが、data.tableのソリューションほど高速ではありませんが、以下に示すコードの最後の行が必要ない場合は、さらにスピードアップする可能性があります。

私たちはd1を動物園のオブジェクトzに分けて読んで、それを分割して各ソースごとに列を持つ多変量時系列を与えます。それをすべての時間を持つゼロ幅の系列にマージし、それをmelt=TRUE引数を使ってデータフレームに戻して、長い形式のdata.frameを取得します。ワイドフォームの多変量動物園シリーズを使用することができれば、最後の行を飛ばすことができます。その場合、さらに速くなります。

library(zoo) 

z <- read.zoo(d1, split = 1, index = 2) # wide form 
zz <- merge(z, zoo(, seq(start(z), end(z), "hour"))) # expand 
fortify(zz, melt = TRUE) # convert to long form data.frame 
+0

ありがとうございます。これはそれを広げる素晴らしい考えです!私は最初に動物園のオブジェクトに変換してそこから移動することは認めていますが、グループ化するとそこにはほとんど到達できませんでした。 – Sotos

関連する問題