加速数据帧匹配

时间:2011-01-15 04:02:40

标签: performance r

我有两个数据帧,非常类似:

data = data.frame(data=cbind(1:12,rep(c(1,2),6),rep(c(1,2,3),4)))
colnames(data)=c('v','h','c')

lookup = data.frame(data=cbind(c(rep(1,3),rep(2,3)),rep(c(1,2,3),2),21:26))
colnames(lookup)=c('h','c','t')

我想从数据$ v中减去查找$ t,其中h和c列匹配。

我认为这样的事情会起作用

data$v-lookup$t[lookup$h==data$h&lookup$c==data$c]

但并不神奇地知道我想隐式迭代数据行

我最终做了这个

myt = c()
for(i in 1:12) {
myt[i] = lookup$t[lookup$h==data$h[i]&lookup$c==data$c[i]]
}

工作正常,但我希望有人可以建议一种不涉及循环的更明智的方法。

4 个答案:

答案 0 :(得分:8)

听起来你可以合并,然后做数学运算:

dataLookedUp <- merge(data, lookup)
dataLookedUp$newValue <- with(dataLookedUp, v - t )

对于您的真实数据,合并和计算更快吗?

如果数据和/或查找非常大,您可以使用data.table在合并之前创建索引以加快速度。

答案 1 :(得分:6)

替代方案1.)对于那些习惯于SQL查询的人更熟悉,而且2.)通常比标准合并更快,就是使用sqldf包。 (请注意,在Mac OS X上,您可能希望安装sqlf所依赖的Tcl / Tk。)另外,sqldf默认情况下会自动将字符串转换为因子。

install.packages("sqldf")
library(sqldf)
data <- data.frame(v = 1:12, h = rep(c("one", "two"), 6), c = rep(c("one", "two", "three"), 4))
lookup <- data.frame(h = c(rep("one", 3), rep("two", 3)), c = rep(c("one", "two", "three"), 2), t =  21:26)
soln <- sqldf("select * from data inner join lookup using (h, c)")
soln <- transform(soln, v.minus.t = v - t)

答案 2 :(得分:4)

使用整数列,我认为您无法改进JD的产品,但如果您在合并的列中有字符串,则可以使用as.factor创建因子,加速merge取决于您的数据集的大小以及您预期的合并/排序数量:

data <- data.frame(v = 1:12, h = rep(c("one", "two"), 6), c = rep(c("one", "two", "three"), 4))
lookup <- data.frame(h = c(rep("one", 3), rep("two", 3)), c = rep(c("one", "two", "three"), 2), t =  21:26)
data <- transform(data, h = as.factor(h), c = as.factor(c))
lookup <- transform(lookup, h = as.factor(h), c = as.factor(c))
temp <- merge(data, lookup)
temp <- transform(temp, v.minus.t = v - t)

答案 3 :(得分:1)

这非常适合data.table使用而不是

library(data.table)
data <- as.data.table(data)
lookup <- as.data.table(lookup)
setkey(data, h, c)
setkey(lookup, h,c)

data[lookup, list(v,t, newValue = v-t)]