我有一个很大的data.frame(5,000万行),需要找到匹配多列条件的索引。
我制作了一个玩具示例来说明问题。
[我读到here,通过data.tables搜索比通过data.frames搜索更快,因此我将data.frame转换为data.table对象
cases<-c(1,3,5)
women<-c("Julia", "Judith", "Juno", "Jane", "Joanna")
data.df<-data.frame("id" = 1:5, "age" = c(20, 30, 40, 50, 60), "name" = c("Joanna","Joe", "Julia", "Juno", "John"))
library(data.table)
data.dt<-as.data.table(data.df)
setkey(data.dt, "id")
我希望结果向量包含通过多列标准的记录的年龄值,在这种情况下为20、40,NA。我使用for循环进行搜索(这可能是一种愚蠢的方法,在此非常感谢您提供任何提示)
results<-vector()
for (i in 1:length(cases)){
which_id<-cases[i]
ind<-data.dt[id==which_id & name %in% women, which=TRUE]
if(length(ind)==0){results[i]<-NA}
else{results[i]<-data.dt$age[ind]}
}
这将在较小的数据集上执行,但如果有500K条记录,而data.df中有50M条记录,则将花费超过12个小时来运行。必须有一种更简单的方法,任何人都可以给出提示吗?
我假设您期望ind
的长度为1或0(意味着ID都不同)。
然后,您可以使用{dplyr}快速执行此操作:
library(dplyr)
results2 <- data.df %>%
slice(match(cases, id)) %>%
mutate(res = ifelse(name %in% women, age, NA)) %>%
pull(res)
[如果我理解正确,那么OP希望先通过id
过滤其数据集,然后如果在age
中找到了name
,则返回women
(否则将返回NA
。
下面是不同的data.table
方法,它们返回预期的结果
20 40 NA
对于示例情况。但是,生产数据集的性能可能有所不同。
id
过滤,与women
匹配setkey(data.dt, id)
data.dt[cases][name %in% women, Age := age][, Age]
这里,整数匹配被用作,因为OP调用name
已将data.frame()
转换为因数。 (如果name
类型为字符%chin%
,则可以使用。)>
为了确保在没有匹配的情况下返回NA
,将使用就地更新
NA
设置为默认值。请注意,Cole's方法data.dt[J(cases)][name %in% women]
仅返回具有2行的过滤数据集,而不返回预期结果。
id
过滤,与women
结合与上面类似,但是使用联接而不是匹配:
setkey(data.dt, id) data.dt[cases][.(women), on = .(name = V1), Age := age][, Age]
[加入
women
,然后加入cases
此方法首先选择name
与women
匹配的行(通过联接,然后与cases
联接:
setkey(data.dt, id)
data.dt[.(women), on = .(name = V1), nomatch = 0L][cases, age]