簡體   English   中英

如何使用條件函數向量化r中的for循環

[英]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介於startend之間。 NA中的結果值是由於NA在值startend

      [,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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM