【问题标题】:Merge data.table by two variables and closest third通过两个变量和最接近的第三个变量合并 data.table
【发布时间】:2013-12-26 20:47:35
【问题描述】:

我想对 data.tables 执行一项操作,我目前可以成功地使用 data.frames 执行该操作。本质上,它是两个 data.frames 的合并函数,它在 df2 中为 df1 找到许多匹配变量之一的最接近匹配。这段代码如下。

我想在 data.tables 中执行此操作,因为我的 data.frames 非常大,如果我尝试对完整数据完成此操作,我当前的设置会崩溃。 Data.table 可能允许我在完整集上直接完成,但如果不是,我发现在使用多个数据子集时更容易使用 data.table。

我正在寻找 df2 中的 Id(及其对应的 value),它与 df1 中的 States value 通过变量 MMvariable(在此data.frame 方法,如果存在最接近的匹配关系(例如,存在正 1 和负 1 的值),则可能发生多个配对)。使用 data.frames 时,我得到的解决方案如下final。我不知道如何设置 data.table 给我相同的结果。我已经尝试过我的钥匙的变体,下面是一个例子。我在代码中引用的 data.frame 问题中有一个answer using 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]

【问题讨论】:

  • 您的示例中数据框final 中的结果似乎与您要获得的内容的描述不匹配。例如,为什么组合 (state=AK, variable=TMN, MM=1) 在final 中产生两行,不应该只产生一个最匹配的 Id 吗?
  • @YT 谢谢,data.frame 'final' 的代码中缺少"State"

标签: r merge dataframe data.table


【解决方案1】:

不确定这是否是实现您想要的最佳方式,但这是一种类似于您对数据框所做的方法,仅使用 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 中的结果不同(State=AK, MM=3, variable=TMX),即使根据您的描述,上述方法也不会返回匹配项应该返回匹配项。

【讨论】:

  • final_dt &lt;- res[, .SD[abs(value.x - value.y) == min(abs(value.x - value.y))], by=c("State", "MM", "variable")] 这行是否翻译为:取res 的子集,其中 value.x - value.y 是最小值?
  • 是的,如果加上by子句,即转化为:对于每个State,MM,variable组合,返回res中value.x - value.y等于的行子集最小值(如果有多个差异等于最小值,则后一位确保您可以按组获得多个命中)。
猜你喜欢
  • 2023-03-19
  • 2018-01-12
  • 1970-01-01
  • 2015-02-07
  • 2012-09-23
  • 2017-01-08
  • 1970-01-01
  • 2015-01-17
  • 2021-02-12
相关资源
最近更新 更多