[英]Select rows within a particular time range
我有一個像這樣的數據框:
TimeStamp Category
2013-11-02 07:57:18 AM 0
2013-11-02 08:07:19 AM 0
2013-11-02 08:07:21 AM 0
2013-11-02 08:07:25 AM 1
2013-11-02 08:07:29 AM 0
2013-11-02 08:08:18 AM 0
2013-11-02 08:09:20 AM 0
2013-11-02 09:04:18 AM 0
2013-11-02 09:05:22 AM 0
2013-11-02 09:07:18 AM 0
我要做的是在“ Category
為“ 1”時選擇+ -10分鍾的時間范圍。
對於這種情況,因為category = 1
在2013-11-02 08:07:25 AM
,所以我想選擇07:57:25 AM to 08:17:25 AM
內的所有行。
處理此任務的最佳方法是什么?
此外,每個時間范圍可能會有多個“ 1”。 (實際數據幀更加復雜,它包含多個具有不同用戶的TimeStamp,即還有一個名為“ UserID”的列)
在基礎R中,無需進行潤滑或其他任何操作(假設您要將TimeStamp轉換為POSIXct
對象),例如:
df$TimeStamp <- as.POSIXct(TimeStamp, format = "%Y-%m-%d %I:%M:%S %p")
df[with(df, abs(difftime(TimeStamp[Category==1],TimeStamp,units="mins")) <= 10 ),]
# TimeStamp Category
#2 2013-11-02 08:07:19 0
#3 2013-11-02 08:07:21 0
#4 2013-11-02 08:07:25 1
#5 2013-11-02 08:07:29 0
#6 2013-11-02 08:08:18 0
#7 2013-11-02 08:09:20 0
如果您有多個1
,則必須像這樣循環遍歷:
check <- with(df,
lapply(TimeStamp[Category==1], function(x) abs(difftime(x,TimeStamp,units="mins")) <= 10 )
)
df[do.call(pmax, check)==1,]
這是我將如何使用data.table::foverlaps
來解決這個data.table::foverlaps
首先,將TimeStamp
轉換為適當的POSIXct
library(data.table)
setDT(df)[, TimeStamp := as.POSIXct(TimeStamp, format = "%Y-%m-%d %I:%M:%S %p")]
然后,我們將創建一個臨時數據集,其中Category == 1
要加入。 我們還將通過“開始”和“結束”列創建一個“結束”列和key
df2 <- setkey(df[Category == 1L][, TimeStamp2 := TimeStamp], TimeStamp, TimeStamp2)
然后,我們將對df
進行相同操作,但將間隔設置為10分鍾
setkey(df[, `:=`(start = TimeStamp - 600, end = TimeStamp + 600)], start, end)
然后,剩下要做的就是按照匹配的概率運行foverlaps
和子集
indx <- foverlaps(df, df2, which = TRUE, nomatch = 0L)$xid
df[indx, .(TimeStamp, Category)]
# TimeStamp Category
# 1: 2013-11-02 08:07:19 0
# 2: 2013-11-02 08:07:21 0
# 3: 2013-11-02 08:07:25 1
# 4: 2013-11-02 08:07:29 0
# 5: 2013-11-02 08:08:18 0
# 6: 2013-11-02 08:09:20 0
這似乎可行:
數據:
根據@DavidArenburg的評論(以及他的回答中所述),將timestamp列轉換為POSIXct
對象的正確方法是(如果尚未):
df$TimeStamp <- as.POSIXct(df$TimeStamp, format = "%Y-%m-%d %I:%M:%S %p")
解:
library(lubridate) #for minutes
library(dplyr) #for between
pickrows <- function(df) {
#pick category == 1 rows
df2 <- df[df$Category==1,]
#for each timestamp create two variables start and end
#for +10 and -10 minutes
#then pick rows between them
lapply(df2$TimeStamp, function(time) {
start <- time - minutes(10)
end <- time + minutes(10)
df[between(df$TimeStamp, start, end),]
})
}
#run function
pickrows(df)
輸出:
> pickrows(df)
[[1]]
TimeStamp Category
2 2013-11-02 08:07:19 0
3 2013-11-02 08:07:21 0
4 2013-11-02 08:07:25 1
5 2013-11-02 08:07:29 0
6 2013-11-02 08:08:18 0
7 2013-11-02 08:09:20 0
請記住,如果有多個Category==1
行,則輸出,我的函數的輸出將是一個列表(在這種情況下,它只有一個元素),因此需要do.call(rbind, pickrows(df))
將所有內容組合到一個data.frame中。
使用lubridate:
df$TimeStamp <- ymd_hms(df$TimeStamp)
span10 <- (df$TimeStamp[df$Category == 1] - minutes(10)) %--% (df$TimeStamp[df$Category == 1] + minutes(10))
df[df$TimeStamp %within% span10,]
TimeStamp Category
2 2013-11-02 08:07:19 0
3 2013-11-02 08:07:21 0
4 2013-11-02 08:07:25 1
5 2013-11-02 08:07:29 0
6 2013-11-02 08:08:18 0
7 2013-11-02 08:09:20 0
我個人喜歡@thelatemail提供的基本R答案的簡單性。 但是只是為了好玩,我將使用data.table
滾動聯接提供另一個答案,這與 @DavidArenburg提供的重疊范圍聯接解決方案相反。
require(data.table)
dt_1 = dt[Category == 1L]
setkey(dt, TimeStamp)
ix1 = dt[.(dt_1$TimeStamp - 600L), roll=-Inf, which=TRUE] # NOCB
ix2 = dt[.(dt_1$TimeStamp + 600L), roll= Inf, which=TRUE] # LOCF
indices = data.table:::vecseq(ix1, ix2-ix1+1L, NULL) # not exported function
dt[indices]
# TimeStamp Category
# 1: 2013-11-02 08:07:19 0
# 2: 2013-11-02 08:07:21 0
# 3: 2013-11-02 08:07:25 1
# 4: 2013-11-02 08:07:29 0
# 5: 2013-11-02 08:08:18 0
# 6: 2013-11-02 08:09:20 0
即使您有多個單元格的Category
為1,AFAICT,這也應該可以正常工作。 將其包裝為此類data.table
操作的功能data.table
...
PS:請參閱其他文章,以將TimeStamp
轉換為POSIXct格式。
這是我用dplyr
和lubridate
解決方案。 步驟如下:
發現其中category ==1
,添加到這個, +
和-
10分鍾與lubridate
的minutes
以簡單的c(-1, 1) * minutes(10)
接着使用filter
,以子集基於存儲在所述兩個間隔rang
矢量。
library(lubridate)
library(dplyr)
wi1 <- which(dat$Category == 1 )
rang <- dat$TimeStamp[wi1] + c(-1,1) * minutes(10)
dat %>% filter(TimeStamp >= rang[1] & TimeStamp <= rang[2])
TimeStamp Category
1 2013-11-02 08:07:19 0
2 2013-11-02 08:07:21 0
3 2013-11-02 08:07:25 1
4 2013-11-02 08:07:29 0
5 2013-11-02 08:08:18 0
6 2013-11-02 08:09:20 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.