当一个是查找表时如何加入 data.tables?

Posted

技术标签:

【中文标题】当一个是查找表时如何加入 data.tables?【英文标题】:How to join data.tables when one is a lookup table? 【发布时间】:2014-06-21 01:22:03 【问题描述】:

我在将简单的 data.table 连接示例应用于更大 (10GB) 的数据集时遇到问题。 merge() 在具有较大数据集的 data.frames 上工作得很好,尽管我很想利用 data.table 中的速度。谁能指出我对 data.table 的误解(尤其是错误消息)?

这是一个简单的例子(来自这个线程:Join of two data.tables fails)。

# The data of interest.
(DT <- data.table(id    = c(rep(1154:1155, 2), 1160),
                  price = c(1.99, 2.50, 15.63, 15.00, 0.75), 
                  key   = "id"))

     id price
1: 1154  1.99
2: 1154 15.63
3: 1155  2.50
4: 1155 15.00
5: 1160  0.75

# Lookup table.
(lookup <- data.table(id      = 1153:1160, 
                      version = c(1,1,3,4,2,1,1,2), 
                      yr      = rep(2006, 4), 
                      key     = "id"))

     id version   yr
1: 1153       1 2006
2: 1154       1 2006
3: 1155       3 2006
4: 1156       4 2006
5: 1157       2 2006
6: 1158       1 2006
7: 1159       1 2006
8: 1160       2 2006

# The desired table.  Note: lookup[DT] works as well.
DT[lookup, allow.cartesian = T, nomatch=0]

     id price version   yr
1: 1154  1.99       1 2006
2: 1154 15.63       1 2006
3: 1155  2.50       3 2006
4: 1155 15.00       3 2006
5: 1160  0.75       2 2006

较大的数据集由两个 data.frames 组成:temp.3561(感兴趣的数据集)和 temp.versions(查找数据集)。它们分别具有与 DT 和查找(上图)相同的结构。使用 merge() 效果很好,但是我对 data.table 的应用显然存在缺陷:

# Merge data.frames: works just fine
long.merged         <- merge(temp.versions, temp.3561, by = "id")

# Convert the data.frames to data.tables
DTtemp.3561         <- as.data.table(temp.3561)
DTtemp.versions     <- as.data.table(temp.versions)

# Merge the data.tables: doesn't work
setkey(DTtemp.3561, id)
setkey(DTtemp.versions, id)
DTlong.merged       <- merge(DTtemp.versions, DTtemp.3561, by = "id")

Error in vecseq(f__, len__, if (allow.cartesian) NULL else as.integer(max(nrow(x),  : 
  Join results in 11277332 rows; more than 7946667 = max(nrow(x),nrow(i)). Check for duplicate 
key values in i, each of which join to the same group in x over and over again. If that's ok, 
try including `j` and dropping `by` (by-without-by) so that j runs for each group to avoid the 
large allocation. If you are sure you wish to proceed, rerun with allow.cartesian=TRUE. 
Otherwise, please search for this error message in the FAQ, Wiki, Stack Overflow and datatable-
help for advice.

DTtemp.versions 具有与查找相同的结构(在简单示例中),键“id”由 779,473 个唯一值(无重复)组成。

DTtemp3561 具有与 DT 相同的结构(在简单示例中)加上一些其他变量,但它的键“id”只有 829 个唯一值,尽管有 7,946,667 个观察值(大量重复)。

由于我只是尝试将 DTtemp.versions 中的版本号和年份添加到 DTtemp.3561 中的每个观察值,因此合并的 data.table 应该具有与 DTtemp.3561 (7,946,667) 相同的观察值。具体来说,我不明白为什么 merge() 在使用 data.table 时会产生“多余”的观察结果,而在使用 data.frame 时却不会。

同样

# Same error message, but with 12,055,777 observations
altDTlong.merged   <- DTtemp.3561[DTtemp.versions]

# Same error message, but with 11,277,332 observations
alt2DTlong.merged  <- DTtemp.versions[DTtemp.3561]

包括 allow.cartesian=T 和 nomatch=0 不会删除“多余”的观察结果。

奇怪的是,如果我将感兴趣的数据集截断为具有 10 个观测值,merge() 在 data.frames 和 data.tables 上都可以正常工作。

# Merge short DF: works just fine
short.3561         <- temp.3561[-(11:7946667),]
short.merged       <- merge(temp.versions, short.3561, by = "id")

# Merge short DT
DTshort.3561       <- data.table(short.3561, key = "id")
DTshort.merged     <- merge(DTtemp.versions, DTshort.3561, by = "id")

我已经阅读了常见问题解答(http://datatable.r-forge.r-project.org/datatable-faq.pdf,尤其是 1.12)。您建议如何考虑这个问题?

【问题讨论】:

@Arun,在提出这个问题之前,我实际上已经阅读了您链接到的帖子,但没有真正掌握这个概念。可能是因为merge(DTtemp.versions, DTtemp.3561, by = "id", allow.cartesian = TRUE) 也返回了 11,227,332 个观察值(nomatch 不会改变这一点)。也许这就是为什么我对 allow.cartesian 正在做什么或没有做什么感到困惑。 @Arun,你是对的:我不清楚为什么 a) merge() 不适用于这些 data.tables (我会尝试查看一个更大的工作示例为此),以及 b)如何使用 DT[lookup,...] 类型的结构来执行此操作(因为 allow.cartesian=T 和 nomatch=0 似乎并没有放弃对“多余”的观察大数据集)。但是 merge() 确实适用于原始 data.frames,所以我并非没有追索权 【参考方案1】:

谁能指出我对 data.table 的误解(尤其是错误消息)?

带你直接回答。错误信息

加入结果为 11277332 行;超过 7946667 = max(nrow(x),nrow(i))。检查 i...中的重复键值...

表示您的连接结果具有比通常情况预期更多的值。这意味着查找表键具有重复项,这会导致连接时出现多个匹配项。

如果它不能回答你的问题,你应该重述它。

【讨论】:

以上是关于当一个是查找表时如何加入 data.tables?的主要内容,如果未能解决你的问题,请参考以下文章

合并多个data.tables

加入具有重复行数据的表时如何获得正确的 SUM()?

Level 1-Lesson 9. Excel & Data Tables

加入表时性能缓慢

如何使用 Azure.Data.Tables 跳过、获取和订购?

如何使用 Azure.Data.Tables.TableClient 进行事务处理?