是否有一种有效的方法可以向后搜索R中的大矢量?

时间:2019-11-11 12:11:54

标签: r dataframe for-loop lookup

我有一个10+百万个元素的向量。 我需要找到满足给定条件A的所有元素(例如,id loaded_date data data_json 1 2019-10-25 Same data as before {"collection": {"row": {"field": [{"-name": "Item Key","-type": "text","-value": "Haircolour - Avstemming kunder - OMT"},{"-name": "Created","-type": "datetime","-value": "2019-10-25 17:35:17Z"},{"-name": "Type","-type": "text","-value": "Session Provisioning Failure"}]}}} 2 2019-10-25 Same data as before {"collection": {"row": {"field": [{"-name": "Item Key","-type": "text","-value": "Haircolour - Avstemming kunder - OMT"},{"-name": "Created","-type": "datetime","-value": "2019-10-25 17:51:32Z"},{"-name": "Type","-type": "text","-value": "Session Provisioning Failure"}]}}} 3 2019-02-23 Same data as before {"collection": {"row": {"field": [{"-name": "Item Key","-type": "text","-value": "Haircolour - Hent klienter til kø"},{"-name": "Last Generation Time","-type": "datetime","-value": "2019-02-23 11:00:36Z"},{"-name": "Priority","-type": "number","-value": "-3"}]}}} 行的X <2)。 从这些元素的每一个中,我都需要向后浏览向量,并标记所有满足条件B的先前元素(例如,对于i %in% c(6,10),X <4)。

例如,给定以下X列,我希望最终结果为i %in% c(8:10) and c(5:6)列。如果B不在满足A的元素之前,我对B为真的元素不感兴趣,因此行flag2具有i == 2

flag2 == 0

产生flag1的第一个操作非常简单且非常快速:

  i  |  X  | flag1 | flag2
---------------------------
  1  |  4  |   0   |   0
  2  |  3  |   0   |   0
  3  |  6  |   0   |   0
  4  |  9  |   0   |   0
  5  |  3  |   0   |   1
  6  |  1  |   1   |   1
  7  |  9  |   0   |   0
  8  |  3  |   0   |   1
  9  |  2  |   0   |   1
 10  |  1  |   1   |   1

我用以下for循环实现了第二个操作,它给出了所需的结果,但是给定的数据量却非常耗时。

# locate all occurrences of X < 2
my_data$flag1 = dplyr::case_when(my_data$X < 2 ~ 1, T ~ 0)

有什么办法可以更有效地做到这一点?

3 个答案:

答案 0 :(得分:1)

希望以下内容可以播种。 它是subsetting,并且将flag的索引移动一个位置,然后重复该操作直到不再标记为止:

my_data  <- data.frame(X=c(4,3,6,9,3,1,9,3,2,1))

my_data$flag1 <- my_data$X < 2
my_data$flag2 <-  my_data$flag1
repeat {
  tt <- my_data$X < 4 & c(my_data$flag2[-1], FALSE)
  if(all(!(tt & !my_data$flag2))) break
  my_data$flag2[tt]  <- TRUE
}
my_data
   X flag1 flag2
1  4 FALSE FALSE
2  3 FALSE FALSE
3  6 FALSE FALSE
4  9 FALSE FALSE
5  3 FALSE  TRUE
6  1  TRUE  TRUE
7  9 FALSE FALSE
8  3 FALSE  TRUE
9  2 FALSE  TRUE
10 1  TRUE  TRUE

或使用Reduce

my_data  <- data.frame(X=c(4,3,6,9,3,1,9,3,2,1))

my_data$flag1 <- my_data$X < 2
my_data  <- my_data[nrow(my_data):1,]
fun <- function(x, y) {c(y[[1]] || (x[[1]] && y[[2]]), FALSE)}
my_data$flag2  <- do.call(rbind, Reduce(fun
  , as.data.frame(rbind(my_data$flag1, my_data$X < 4))[,-1]
  , c(my_data$flag1[1], FALSE), accumulate = TRUE))[,1]
my_data  <- my_data[nrow(my_data):1,]
my_data
#   X flag1 flag2
#1  4 FALSE FALSE
#2  3 FALSE FALSE
#3  6 FALSE FALSE
#4  9 FALSE FALSE
#5  3 FALSE  TRUE
#6  1  TRUE  TRUE
#7  9 FALSE FALSE
#8  3 FALSE  TRUE
#9  2 FALSE  TRUE
#10 1  TRUE  TRUE

答案 1 :(得分:1)

这是使用accumulate包中的purrr函数的另一种可能性:

library(tidyverse)

my_data  <- data.frame(X=c(4,3,6,9,3,1,9,3,2,1))

my_fun <- function(flag1, xlag) if ((flag1 == 1 & xlag < 4) | xlag < 2) 1 else 0

my_data %>%
  mutate(flag1 = if_else(X < 2, 1, 0),
         flag2 = rev(accumulate(rev(X), my_fun, .init = last(flag1))[-1]))

   X flag1 flag2
1  4     0     0
2  3     0     0
3  6     0     0
4  9     0     0
5  3     0     1
6  1     1     1
7  9     0     0
8  3     0     1
9  2     0     1
10 1     1     1

答案 2 :(得分:0)

如果可以使用data.table软件包,那么使用以下方法在一千万行中花费不到1秒的时间:

library(data.table)
nr <- 10e6
set.seed(0L)
my_data <- data.frame(X=sample(1:9, nr, TRUE))

system.time({
    setDT(my_data)[, flag2 := { 
        flag1 <- X < 2
        b <- rleid(X < 4)
        +(b %in% b[flag1])
    }]
})

#   user  system elapsed 
#   0.30    0.12    0.42 

输出:

          X flag2
       1: 9     0
       2: 4     0
       3: 7     0
       4: 1     1
       5: 2     1
      ---        
 9999996: 6     0
 9999997: 1     1
 9999998: 9     0
 9999999: 6     0
10000000: 1     1

head(my_data, 10)

    X flag2
 1: 9     0
 2: 4     0
 3: 7     0
 4: 1     1
 5: 2     1
 6: 7     0
 7: 2     1
 8: 3     1
 9: 1     1
10: 5     0