[英]how to vectorize a for loop in r with conditionals
我在這個任務上苦苦掙扎了很長時間,因此我想請教您。
在df1中,我試圖基於df1中的信息以及df2中的信息添加新列。 因此,在df2中,只要兩個dfs中的位置都匹配且df2中的時間戳在df1給定的間隔內,就應創建ID列。否則返回0
。 問題是它們的長度不相等。 我知道如何編寫嵌套的for循環,但是它很丑陋,並且永遠需要運行。 我嘗試使用提議的sapply作為類似問題的解決方案,但由於df長度不同,因此無法運行
我發現了這個線程[ 加快R中的循環操作 ,但是由於條件條件作用於其上的dfs的長度不同,因此我無法獲得此解決方案。
這是我的數據:
df1 <- structure(list(ID = c(NA, NA, 10035010L), location = c("barge",
"barge", "barge"), start = structure(c(NA, NA,
1427301960), class = c("POSIXct", "POSIXt"), tzone = ""), end = structure(c(NA,
NA, 1437418440), class = c("POSIXct", "POSIXt"), tzone = "")), .Names = c("ID",
"location", "start", "end"), row.names = c(NA, 3L), class = "data.frame")
df2<-structure(list(time = structure(c(1419062220, 1419063120, 1427325120,
1427325240, 1427325360, 1427325540, 1427325660, 1427326680, 1427568960,
1427569320, 1427569500), class = c("POSIXct", "POSIXt"), tzone = ""),
location = c("barge", "barge", "barge",
"barge", "barge", "barge", "barge",
"barge", "barge", "barge", "barge"
)), row.names = c(222195L, 222196L, 186883L, 186884L, 186885L,
186886L, 186887L, 186888L, 186930L, 186931L, 186932L), class = "data.frame", .Names = c("time",
"location"))
更新 :我決定使用dplyr軟件包,因為我對此感到滿意,並在較大的數據集中使用了它。 但是,由於包括工作站ID時跨位置的輸出不一致,因此會出現問題。
考慮包含站的相同但經過稍微修改的數據集,以查看結果差異:
df3<-structure(list(time = structure(c(1419061860, 1419062220, 1419063120,
1427325120, 1427325240, 1427325360, 1427325540, 1427325660, 1427326680,
1427568960, 1427569320), class = c("POSIXct", "POSIXt"), tzone = ""),
station = c(104667L, 104667L, 104667L, 124083L, 124083L,
124083L, 124083L, 124083L, 124083L, 124083L, 124083L), location = c("barge",
"barge", "barge", "barge", "barge",
"barge", "barge", "barge", "barge",
"barge", "barge")), row.names = 879:889, class = "data.frame", .Names = c("time", "station", "location"))
和
df4<-structure(list(station = c(124083L, 113071L), location = c("barge",
"barge"), ID = c(10035010L, NA), start = structure(c(1427301960,
NA), class = c("POSIXct", "POSIXt"), tzone = ""), end = structure(c(1437418440,
NA), class = c("POSIXct", "POSIXt"), tzone = "")), row.names = 3:4, class = "data.frame", .Names = c("station",
"location", "ID", "start", "end"))
當我運行dplyr解決方案時,
df3 %>% left_join(., df4) %>%
mutate(ID = ifelse(time >= start & time < end, ID, 0))
它不會返回相同的輸出,即,在第一種情況下,返回的數據集是原始數據的倍數,在最后一種情況下,返回的數據集的長度相等。 我只是不知道為什么會有所不同。 這使得無法使用filter()函數。 任何解決此問題的建議將不勝感激。 謝謝
前幾天,我只是使用了一些老式的SQL代碼來解決類似的問題。 嘗試這個
library(sqldf)
sqldf('
SELECT
df2.*
,CASE WHEN df1.location is NOT NULL THEN 1 ELSE 0 END AS id
FROM df2
LEFT JOIN df1 ON df2.time > df1.start AND df2.time < df1.end
')
如果要在大型數據集上執行此操作,則在過濾器刪除不必要的行之前,由於聯接變為笛卡爾坐標,因此我將避免使用上面的dplyr代碼。 我希望有人盡快在dplyr中添加條件聯接
您可以使用dplyr
兩個數據幀並按以下步驟進行突變:
library(dplyr)
df2 %>% left_join(., df1) %>%
mutate(ID = ifelse(time > start & time < end, 1, 0))
輸出將如下所示(如果願意,您可以使用NA filter
行):
time location ID start end
1 2014-12-20 02:57:00 barge NA <NA> <NA>
2 2014-12-20 02:57:00 barge NA <NA> <NA>
3 2014-12-20 02:57:00 barge 0 2015-03-25 12:46:00 2015-07-20 14:54:00
4 2014-12-20 03:12:00 barge NA <NA> <NA>
5 2014-12-20 03:12:00 barge NA <NA> <NA>
6 2014-12-20 03:12:00 barge 0 2015-03-25 12:46:00 2015-07-20 14:54:00
7 2015-03-25 19:12:00 barge NA <NA> <NA>
8 2015-03-25 19:12:00 barge NA <NA> <NA>
9 2015-03-25 19:12:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
10 2015-03-25 19:14:00 barge NA <NA> <NA>
11 2015-03-25 19:14:00 barge NA <NA> <NA>
12 2015-03-25 19:14:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
13 2015-03-25 19:16:00 barge NA <NA> <NA>
14 2015-03-25 19:16:00 barge NA <NA> <NA>
15 2015-03-25 19:16:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
16 2015-03-25 19:19:00 barge NA <NA> <NA>
17 2015-03-25 19:19:00 barge NA <NA> <NA>
18 2015-03-25 19:19:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
19 2015-03-25 19:21:00 barge NA <NA> <NA>
20 2015-03-25 19:21:00 barge NA <NA> <NA>
21 2015-03-25 19:21:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
22 2015-03-25 19:38:00 barge NA <NA> <NA>
23 2015-03-25 19:38:00 barge NA <NA> <NA>
24 2015-03-25 19:38:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
25 2015-03-28 14:56:00 barge NA <NA> <NA>
26 2015-03-28 14:56:00 barge NA <NA> <NA>
27 2015-03-28 14:56:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
28 2015-03-28 15:02:00 barge NA <NA> <NA>
29 2015-03-28 15:02:00 barge NA <NA> <NA>
30 2015-03-28 15:02:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
31 2015-03-28 15:05:00 barge NA <NA> <NA>
32 2015-03-28 15:05:00 barge NA <NA> <NA>
33 2015-03-28 15:05:00 barge 1 2015-03-25 12:46:00 2015-07-20 14:54:00
您可以使用outer
將函數應用於任意長度的兩個向量。 它應該僅進行必要的計算(即唯一的組合)。 對於您的情況,您將對邏輯測試使用外部三遍,然后將結果合並為一個邏輯矩陣。
gets_id <- outer(df2$location, df1$location, '==') &
outer(df2$time, df1$start, '>=') &
outer(df2$time, df1$end, '<=')
這將產生以下輸出。 TRUE值表示location
是數據幀之間的匹配,並且time
介於start
和end
之間。 NA
中的結果值是由於NA
在值start
和end
。
[,1] [,2] [,3]
[1,] NA NA FALSE
[2,] NA NA FALSE
[3,] NA NA TRUE
[4,] NA NA TRUE
[5,] NA NA TRUE
[6,] NA NA TRUE
[7,] NA NA TRUE
[8,] NA NA TRUE
[9,] NA NA TRUE
[10,] NA NA TRUE
[11,] NA NA TRUE
獲得結果后,您可以隨意操作它。 以下將適用於您的用例。
assignments <- which(gets_id, arr.ind=TRUE)
df2$id[assignments[,'row']] <- df1$ID[assignments[,'col']]
導致:
time location id
222195 2014-12-20 02:57:00 barge NA
222196 2014-12-20 03:12:00 barge NA
186883 2015-03-25 19:12:00 barge 10035010
186884 2015-03-25 19:14:00 barge 10035010
186885 2015-03-25 19:16:00 barge 10035010
186886 2015-03-25 19:19:00 barge 10035010
186887 2015-03-25 19:21:00 barge 10035010
186888 2015-03-25 19:38:00 barge 10035010
186930 2015-03-28 14:56:00 barge 10035010
186931 2015-03-28 15:02:00 barge 10035010
186932 2015-03-28 15:05:00 barge 10035010
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.