r - 当我们为向量的所有元素查找所有匹配索引时,R 中是否有一个函数可以避免使用循环?
问题描述
我有这个 for 循环,它返回向量中每个元素的第一个匹配索引,但它非常慢(nrow(data)> 50 000)
例子:
id1 <- c(1,5,8,10)
id2 <- c(5,8,10,1)
data <- data.frame(id1,id2, idx = 1:length(id1))
结果应该是:
data$new_id
4 1 2 3
data$new_id <- NA
for(i in 1:nrow(data)){
data$new_id[i] <- which(data$id2 == data$id1[i])
}
我发现这适用于小数据帧,但不幸的是 R 返回“错误:无法分配大小为 22.2 Gb 的向量”
A <- outer(data$id1,data$id2, "==")
data <- data %>%
mutate(new_id = which(t(A)),
id0 = 0:(nrow(data)-1),
new_id = new_id-(nrow(data))*id0)
是否存在其他解决方案来执行此索引?
解决方案
我们可以使用match
非常快的base R
函数。在这里,我们只是匹配数据集的两列,甚至没有尝试将两个数据集放在一起
with(data, match(id1, id2))
#[1] 4 1 2 3
为了加快速度,请使用fmatch
fromfastmatch
library(fastmatch)
with(data, fmatch(id1, id2))
基准
set.seed(24)
data1 <- data.frame(id1 = sample(1e7), id2 = sample(1e7))
system.time(with(data1, match(id1, id2)))
# user system elapsed
# 1.635 0.079 1.691
system.time(with(data1, fmatch(id1, id2)))
# user system elapsed
# 1.155 0.062 1.195
system.time({
data2 <- data.table(id = data1$id1)
data3 <- data.table(id = data1$id2)
data2[data3, idx := .I, on = .(id)]
})
# user system elapsed
# 2.306 0.051 2.353
推荐阅读
- windows - 我想用 Vagrant 在 OSX 上运行一个基本的 Windows 来宾,但我不断收到身份验证失败
- swift - 从初始化程序返回而不初始化所有存储的属性Swift Xcode 10.0
- sql - 使用别名或同义词的 SQL Server 跨数据库查询
- sql-server - 在同一查询中为 Oracle 和 SQL Server 转义特殊字符
- php - laravel 5.6 socialite auth by facebook email 为空
- android - 获取 Widevine 许可证服务器密钥
- image-processing - 对角线方向边缘检测
- symfony - 动态类加载 - 尝试从命名空间 _NAMESPACE_ 加载类 _CLASS_
- php - 使用没有错误消息的私人频道时无法从推送者那里获得响应
- python - 如何创建一个包含集合中每个值的字典?