我有两个向量,一个是大约1亿个非唯一元素(整数)的(A),另一个是100万个相同的唯一元素的(B)。我试图得到一个列表,其中包含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天,但速度还是太慢了.
有什么东西可以更快地工作吗?
发布于 2016-06-19 14:33:56
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
的相对性能就越好。
在我的基准order
中,在Debian笔记本电脑上只需要46%的,而在带有2.x GHz CPU的Windows笔记本电脑上,只需要的5%。
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
发布于 2016-06-19 14:34:09
这是快速的:
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
发布于 2016-06-19 14:42:56
我们也可以使用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
..。
https://stackoverflow.com/questions/37908178
复制相似问题