2013-12-09 33 views
1

我想对data.tables执行操作,目前我可以成功地使用data.frames。实质上,它是两个data.frames的合并函数,它为df1找到了df2中匹配变量之一的最接近的匹配项。该代码如下。通过两个变量合并data.table和最接近的第三个

我想这样做是data.tables,因为我data.frames是非常大的,和我的当前设置崩溃,如果我试图完成对全部数据这一操作。 Data.table可能允许我直接在整套数据集上完成它,但如果不是这样,我发现在使用多个数据子集时,data.table更容易处理。

我要找的Id(及其相应value)从具有最接近的匹配由变量State小号value在DF1 MMvariable(在此data.frame方法DF2,多个配对可以发生,如果有最接近的匹配关系(例如存在加1和减1的值))。当使用data.frames时,我在下面得到解决方案final。我不知道如何设置data.table来给我相同的结果。我试过我的钥匙的变体,下面是一个例子。有一个answer在data.frame问题,我在代码中参考使用data.table,但是,我不能让它与我的示例数据工作。

# data.frame method 
# used info from this thread: https://stackoverflow.com/questions/16095680 
df1 <- structure(list(State = structure(c(1L, 1L, 3L, 3L, 2L, 2L, 1L, 
1L, 1L), .Label = c("AK", "CO", "MS"), class = "factor"), MM = c(1L, 
2L, 1L, 2L, 3L, 4L, 3L, 4L, 2L), variable = structure(c(1L, 1L, 
1L, 1L, 2L, 2L, 2L, 2L, 2L), .Label = c("TMN", "TMX"), class = "factor"), 
    value = c(1L, 2L, 3L, 4L, 2L, 3L, 5L, 6L, 7L)), .Names = c("State", 
"MM", "variable", "value"), class = "data.frame", row.names = c(NA, 
-9L)) 
df2 <- structure(list(Id = c(1L, 2L, 3L, 1L, 2L, 3L, 5L, 6L, 7L, 5L, 
6L, 7L, 8L), MM = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 
4L, 5L), variable = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L), .Label = c("TMN", "TMX"), class = "factor"), 
    value = c(1, 2, 3, 2, 3, 4, 2, 3, 5.5, 6.5, 3.5, 2.5, 8)), .Names = c("Id", 
"MM", "variable", "value"), class = "data.frame", row.names = c(NA, 
-13L)) 

#Find rows that match by x and y 
res <- merge(df1, df2, by = c("MM", "variable"), all.x = TRUE) 

res$dif <- abs(res$value.x - res$value.y) 

#Find rows that need to be merged 
res1 <- merge(aggregate(dif ~ MM + variable, data = res, FUN = min), res) 

#Finally merge the result back into df1 
final <- merge(df1, res1[res1$dif <= 1, c("MM", "variable", "State", "Id", "value.y")], all.x = TRUE) 

### one Data.table attempts 
# create data.tables with the same key columns 
keycols1 = c("MM", "variable", "value") 
df1t <- data.table(df1, key = keycols1) 
df2t <- data.table(df2, key = key(df1t)) 
setkey(df1t, value) 
setkey(df2t, value) 
test.final <- df2t[df1t, roll='nearest', allow.cartesian=TRUE] 
+1

结果在数据帧'final'在你的例子似乎并不匹配你所希望得到说明。例如,为什么用组合(状态= AK,变量= TMN,MM = 1)产生'final',它should't只产生一个标识与所述最接近的匹配的两行? –

+0

@YT谢谢,在data.frame'final'代码中缺少''State''' – nofunsally

回答

3

不知道这是为了实现你想要什么是最好的方式,但在这里是一种方法类似于你做数据帧什么,只能用data.tables代替:

dt1 <- data.table(df1) 
dt2 <- data.table(df2) 
res <- merge(dt1, dt2, by = c("MM", "variable"), all.x = TRUE, allow.cartesian=TRUE) 
final_dt <- res[, .SD[abs(value.x - value.y) == min(abs(value.x - value.y))], by=c("State", "MM", "variable")] 

注意,结果final_dt从你的结果不同之处final的(状态= AK,MM = 3,变量= TMX),你的做法并不返回即使根据你的描述匹配应返回匹配。

+0

'final_dt < - res [,.SD [abs(value.x - value.y)== min(abs(value .X - value.y))],通过= C( “国家”, “MM”, “可变”)]'这是否行翻译:取res'的'所述子集,其中value.x - value.y是最低的? – nofunsally

+0

是的,如果添加by子句,即它转换为:对于每个状态,MM,变量组合返回res中的行的子集,其中value.x - value.y等于最小值(后一位确保如果多于一个的差值等于最小值,则可以为每个组获得多个匹配)。 –

相关问题