2017-10-12 105 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 
... 

我的嘗試是利用complete功能使用tidyverse方法,即

library(tidyverse) 

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

然而,約40-45秒後,出現了一個進度條(顯然在某些完美功能中是一個整潔的功能 - 在這種情況下我懷疑是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

相關:[爲數據框中缺失值添加行的最快方法](https://stackoverflow.com/questions/10438969/fastest-way-to-add-rows-for-missing -values-in-a-data-frame/10473931#10473931) – Henrik

+0

@亨利克感謝您的鏈接。我實際上經歷了很多關於填補缺失日期的問題,但其中任何一個都不需要分組。 – 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解決方案那麼快,儘管如果不需要下面顯示的最後一行代碼,那麼存在進一步加速iup的可能性。

我們讀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

相關問題