我有两个向量,一个(A)有大约1亿个非独特元素(整数),另一个(B)有100万个相同的,唯一的元素。我正在尝试获取一个列表,其中包含A中每个B元素的重复实例的索引。
A <- c(2, 1, 1, 1, 2, 1, 1, 3, 3, 2)
B <- 1:3
# would result in this:
[[1]]
[1] 2 3 4 6 7
[[2]]
[1] 1 5 10
[[3]]
[1] 8 9
我首先天真地尝试了这个:
b_indices <- lapply(B, function(b) which(A == b))
这是非常低效的,显然在几年内不会完成。
我尝试的第二件事是创建一个空向量列表,用B的所有元素索引,然后循环通过A,将索引附加到A中每个元素的相应向量。虽然技术上是O(n) ,我不确定重复追加元素的时间。这种方法显然需要2-3天,这仍然太慢......
有什么可以更快地运作吗?
答案 0 :(得分:8)
这很快:
A1 <- order(A, method = "radix")
split(A1, A[A1])
#$`1`
#[1] 2 3 4 6 7
#
#$`2`
#[1] 1 5 10
#
#$`3`
#[1] 8 9
B <- seq_len(1e6)
set.seed(42)
A <- sample(B, 1e8, TRUE)
system.time({
A1 <- order(A, method = "radix")
res <- split(A1, A[A1])
})
# user system elapsed
#8.650 1.056 9.704
答案 1 :(得分:6)
data.table
可以说是处理R中大数据的最有效方式,它甚至可以让你避免一起使用那个100万个长度的数据!
require(data.table)
a <- data.table(x=rep(c("a","b","c"),each=3))
a[ , list( yidx = list(.I) ) , by = x ]
a yidx
1: a 1,2,3
2: b 4,5,6
3: c 7,8,9
使用您的示例数据:
a <- data.table(x=c(2, 1, 1, 1, 2, 1, 1, 3, 3, 2))
a[ , list( yidx = list(.I) ) , by = x ]
a yidx
1: 2 1, 5,10
2: 1 2,3,4,6,7
3: 3 8,9
将此添加到您的基准测试中。我敢说它应该比使用内置函数快得多,如果你大规模测试它。数据越大,data.table
在我的经验中的相对表现就越好。
在我的基准中,我的Debian笔记本电脑上的order
只需要大约46%,而在我的Windows笔记本电脑上只需{5>只有order
,具有8GB RAM和2.x GHz CPU。
B <- seq_len(1e6)
set.seed(42)
A <- data.table(x = sample(B, 1e8, TRUE))
system.time({
+ res <- A[ , list( yidx = list(.I) ) , by = x ]
+ })
user system elapsed
4.25 0.22 4.50
答案 2 :(得分:2)
我们也可以使用dplyr
library(dplyr)
data_frame(A) %>%
mutate(B = row_number()) %>%
group_by(A) %>%
summarise(B = list(B)) %>%
.$B
#[[1]]
#[1] 2 3 4 6 7
#[[2]]
#[1] 1 5 10
#[[3]]
#[1] 8 9
在1e5大小的较小数据集中,它提供system.time
# user system elapsed
# 0.01 0.00 0.02
但是如其他帖子中所示的更大的例子,它更慢。但是,这是dplyr
...