2011-01-15 63 views
7

我有兩個dataframes,就像這些:加快數據幀匹配

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,其中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]] 
} 
數據行隱式迭代

這工作正常,但我希望有人可以建議一個更合理的方式,不涉及循環。

回答

8

聽起來像是你可以合併,然後做數學題:

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

爲了您的真實數據,是合併和計算速度更快?

如果數據和/或查找真的很大,您可以使用data.table在合併之前創建索引,以便加快速度。

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) 
+0

在現實中,他們都是字符串,因爲我在創建數據幀可怕。謝謝! – ansate

+0

@ansate - FWIW,你可以用你的'stringsAsFactors'選項和'read.table'選項來修改默認情況下的字符串讀入。默認值應該是讀取字符串作爲因素。 –

6

的替代方案,是1)更熟悉那些習慣於SQL查詢和2)通常比標準的合併速度更快是使用sqldf包。 (請注意,在Mac OS X上,您可能需要安裝Tcl/Tk,而sqldf依賴於它。)作爲額外的好處,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) 
+0

請注意,最後兩行可以這樣組合:'sqldf(「select *,v -t as'v.minus.t'from data join lookup using(h,c)」)' –

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)]