我有一個data.table
(〜30萬行)在POSIXct
格式由datetime
柱,一個id
柱和其他一些列(在本例中,我剛離開一個不相干列x
來證明存在需要保留的其他列)。 A dput
位於帖子的底部。子集的意見,即由至少30分鐘時間不同
head(DT)
# datetime x id
#1: 2016-04-28 16:20:18 0.02461368 1
#2: 2016-04-28 16:41:34 0.88953932 1
#3: 2016-04-28 16:46:07 0.31818101 1
#4: 2016-04-28 17:00:56 0.14711365 1
#5: 2016-04-28 17:09:11 0.54406602 1
#6: 2016-04-28 17:39:09 0.69280341 1
問:對於每個id
,我需要子集只有那些超過30分鐘的時間裏不同的意見。什麼可能是有效的data.table
方法來做到這一點(如果可能,沒有廣泛的循環)?
的邏輯也可以描述爲(像我下面的評論):
每個ID的第一行始終保持。下一行至少應在第一行之後至少保留30分鐘。讓我們假設行 保持爲4行。然後,計算4行和 行5之間的時間差:n和保持第一,通過超過30分鐘的不同等 上
在dput下面,我添加了一個列表keep
來指示在這個例子中應該保留哪些行,因爲它們與每個id保留的先前觀察值相差超過30分鐘。困難在於似乎有必要迭代地計算時間差(或者至少我現在不能想到更有效的方法)。
library(data.table)
DT <- structure(list(
datetime = structure(c(1461853218.81561, 1461854494.81561,
1461854767.81561, 1461855656.81561, 1461856151.81561, 1461857949.81561,
1461858601.81561, 1461858706.81561, 1461859078.81561, 1461859103.81561,
1461852799.81561, 1461852824.81561, 1461854204.81561, 1461855331.81561,
1461855633.81561, 1461856311.81561, 1461856454.81561, 1461857177.81561,
1461858662.81561, 1461858996.81561), class = c("POSIXct", "POSIXt")),
x = c(0.0246136845089495, 0.889539316063747, 0.318181007634848,
0.147113647311926, 0.544066024711356, 0.6928034061566, 0.994269776623696,
0.477795971091837, 0.231625785352662, 0.963024232536554, 0.216407935833558,
0.708530468167737, 0.758459537522867, 0.640506813768297, 0.902299045119435,
0.28915973729454, 0.795467417687178, 0.690705278422683, 0.59414202044718,
0.655705799115822),
id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L),
keep = c(TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE,
FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE)),
.Names = c("datetime", "x", "id", "keep"),
row.names = c(NA, -20L),
class = c("data.table", "data.frame"))
setkey(DT, id, datetime)
DT[, difftime := difftime(datetime, shift(datetime, 1L, NA,type="lag"), units = "mins"),
by = id]
DT[is.na(difftime), difftime := 0]
DT[, difftime := cumsum(as.numeric(difftime)), by = id]
的keep
列的說明:
- 行2:3相差不到30分鐘從第1行 - >刪除
- 第4點的不同通過從第1行超過30分鐘 - >保持
- 行5個dufferes通過小於30分鐘,從4行 - >從4行刪除
- 第6行相差超過30分鐘 - >保持
- ...
所需的輸出:
desiredDT <- DT[(keep)]
感謝我收到了三個專家解答。我測試了1千萬行數據。這是基準的摘錄。
一)一個百萬行
microbenchmark(frank(DT_Frank), roland(DT_Roland), eddi1(DT_Eddi1), eddi2(DT_Eddi2),
times = 3L, unit = "relative")
#Unit: relative
# expr min lq mean median uq max neval
# frank(DT_Frank) 1.286647 1.277104 1.185216 1.267769 1.140614 1.036749 3
# roland(DT_Roland) 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 3
# eddi1(DT_Eddi1) 11.748622 11.697409 10.941792 11.647320 10.587002 9.720901 3
# eddi2(DT_Eddi2) 9.966078 9.915651 9.210168 9.866330 8.877769 8.070281 3
B)10萬行
microbenchmark(frank(DT_Frank), roland(DT_Roland), eddi1(DT_Eddi1), eddi2(DT_Eddi2),
times = 3L, unit = "relative")
#Unit: relative
# expr min lq mean median uq max neval
# frank(DT_Frank) 1.019561 1.025427 1.026681 1.031061 1.030028 1.029037 3
# roland(DT_Roland) 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 3
# eddi1(DT_Eddi1) 11.567302 11.443146 11.301487 11.323914 11.176515 11.035143 3
# eddi2(DT_Eddi2) 9.796800 9.693823 9.526193 9.594931 9.398969 9.211019 3
顯然,@弗蘭克的data.table方法,並@基於羅蘭的RCPP的解決方案是在與具有RCPP性能相似輕微的優勢,而@ eddi的方法仍然很快,但不像其他人一樣表現良好。
然而,當我檢查瞭解決方案的平等,我發現@羅蘭的做法有一個稍微不同的結果比別人:
一)一個百萬行
all.equal(frank(DT_Frank), roland(DT_Roland))
#[1] "Component 「datetime」: Numeric: lengths (982228, 982224) differ"
#[2] "Component 「id」: Numeric: lengths (982228, 982224) differ"
#[3] "Component 「x」: Numeric: lengths (982228, 982224) differ"
all.equal(frank(DT_Frank), eddi1(DT_Eddi1))
#[1] TRUE
all.equal(frank(DT_Frank), eddi2(DT_Eddi2))
#[1] TRUE
B)千萬行
all.equal(frank(DT_Frank), roland(DT_Roland))
#[1] "Component 「datetime」: Numeric: lengths (9981898, 9981891) differ"
#[2] "Component 「id」: Numeric: lengths (9981898, 9981891) differ"
#[3] "Component 「x」: Numeric: lengths (9981898, 9981891) differ"
all.equal(frank(DT_Frank), eddi1(DT_Eddi1))
#[1] TRUE
all.equal(frank(DT_Frank), eddi2(DT_Eddi2))
#[1] TRUE
我現在的假設是,這種差異可能與該differnce是> 30分鐘或>時間= 30分鐘,雖然我不知道這一點呢。最終想法:我決定與@弗蘭克的解決方案一起去,原因有兩個:1.它的表現非常好,幾乎等於Rcpp解決方案,2.它不需要另一個我並不十分喜歡的包熟悉卻又(我使用data.table反正)
這些都是種我認爲一個好的C/C++解決方案是非常有價值的任務。沒有一個明顯的R向量化的方式,寫出你描述的條件在C或C++中應該非常簡單。如果你知道如何編寫可從R調用的C/C++函數,我會建議這條路線。 – nicola
應該很容易與重疊連接,只准備*從*和*到*每個'ID'的日期 – jangorecki
@jangorecki我希望這樣的解決方案存在,但我不知道從和日期apriori。或者你有一個想法如何計算它們? –