我有一個data.table
和一個日期列表。我希望使用函數來過濾和修改行,以檢查列表中是否有日期。使用函數選擇data.table行
# example data
set.seed(1)
tt <- sample(
seq(as.POSIXct("2011-10-02"), as.POSIXct("2014-04-06"),
by = "day"), 10)
IR1 <- data.table(tstamp = sort(tt), dLoc = 1L:10L)
日期列表:
DLSlist <- lapply(
list(dls11t12 = c("2011-10-02", "2012-04-01"),
dls12t13 = c("2012-10-07", "2013-04-07"),
dls13t14 = c("2013-10-06", "2014-04-06"),
dls14t15 = c("2014-10-05", "2015-04-05"),
dls15t16 = c("2015-10-04", "2016-04-03"),
dls16t17 = c("2016-10-02", "2017-04-02")
),
function(X) as.POSIXct(X)
)
我想變換dLoc
如果它屬於內部的任何日期範圍的DLSlist
。我可以做很長的一段如下:
IR1[tstamp > DLSlist[[1]][1] & tstamp < DLSlist[[1]][2], tstamp := tstamp + 60*60]
IR1[tstamp > DLSlist[[2]][1] & tstamp < DLSlist[[2]][2], tstamp := tstamp + 60*60]
IR1[tstamp > DLSlist[[3]][1] & tstamp < DLSlist[[3]][2], tstamp := tstamp + 60*60]
但是,這似乎很容易出錯:一個函數適合這個任務...我的工作沒有奏效。
DLStest <- function(dd, DLSobj) {
any(sapply(DLSobj, function(X) dd %between% X))
}
我應用了它:
IR1[DLStest(tstamp, DLSlist), tstamp := tstamp + 60*60]
但是它沒有工作:所有行的轉化(不僅範圍內的,如已經在我的醜陋的黑客案件碼)。
是否有一些使用函數選擇行的方法 - 或基於多個範圍檢查選擇行的其他方法?
更新(與感謝弗蘭克,誰發現了問題)
您可以返回一個載體或布爾函數確實進行過濾。這個錯誤是我最初的功能。
DLStest_old <- function(dd, DLSobj) {
any(sapply(DLSobj, function(X) dd %between% X))
}
sapply
返回一個對象,誰的class
是matrix
; any
檢查整個matrix
中是否有任意的真值。如果有任何真值,則評估爲單個TRUE
。如果不是,則評估爲單個FALSE
。
使用測試數據:
(IR1[DLStest_old(tstamp, DLSlist), dLoc := dLoc + 1000L])
tstamp dLoc
1: 2011-11-27 01:00:00 1001
2: 2012-04-03 00:00:00 1002
3: 2012-06-01 00:00:00 1003
4: 2012-09-06 00:00:00 1004
5: 2013-03-09 01:00:00 1005
6: 2013-04-25 00:00:00 1006
7: 2013-05-25 00:00:00 1007
8: 2013-12-29 01:00:00 1008
9: 2014-01-09 01:00:00 1009
10: 2014-02-08 01:00:00 1010
解決方法是爲矩陣的每一行分別測試,使用apply
。
DLStest <- function(dd, DLSobj) {
apply(sapply(DLSobj, function(X) dd %between% X), 1, any)
}
這現在工作:
> (IR1[DLStest(tstamp, DLSlist), dLoc := dLoc + 1000L])
tstamp dLoc
1: 2011-11-27 01:00:00 1001
2: 2012-04-03 00:00:00 2
3: 2012-06-01 00:00:00 3
4: 2012-09-06 00:00:00 4
5: 2013-03-09 01:00:00 1005
6: 2013-04-25 00:00:00 6
7: 2013-05-25 00:00:00 7
8: 2013-12-29 01:00:00 1008
9: 2014-01-09 01:00:00 1009
10: 2014-02-08 01:00:00 1010
+1 DLStest(IR1 $ tstamp,DLSlist)給出了預期的結果嗎?我認爲它應該只給出整個tstamp矢量的一個單一的真或假的值。也許如果你添加'by = 1:nrow(IR1)',它會工作...... – Frank
[請參閱此鏈接](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)。給出適當的可重現的例子可能會得到更好更快的答案。 –
@Frank:你說得對,它只給了一個'logi'值。不幸的是,'IR1 [DLStest(tstamp,DLSlist),tstamp:= tstamp + 60 * 60,by = 1:nrow(IR1)]'不起作用。 – ricardo