我有一个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)
有什么办法可以更有效地做到这一点?
答案 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