【问题标题】:Vlookup with data.table in R在 R 中使用 data.table 进行 Vlookup
【发布时间】:2016-06-27 20:40:13
【问题描述】:

首先,让我们从 DataTable 1 (DF1) 开始:

          date id sales cost city  name
 1: 06/19/2016  1   149  101  MTL Bank1
 2: 06/20/2016  1   150  102  MTL Bank1
 3: 06/21/2016  1   151  104  MTL Bank1
 4: 06/22/2016  1   152  107  MTL Bank1
 5: 06/23/2016  1   155   99  MTL Bank1
 6: 06/19/2016  2    84   55   NY Bank2
 7: 06/20/2016  2    83   55   NY Bank2
 8: 06/21/2016  2    80   56   NY Bank2
 9: 06/22/2016  2    81   57   NY Bank2
10: 06/23/2016  2    97   58   NY Bank2

library(data.table)
DF1 <- data.table(c("06/19/2016", "06/20/2016", "06/21/2016", "06/22/2016", 
                    "06/23/2016", "06/19/2016", "06/20/2016", "06/21/2016",
                    "06/22/2016", "06/23/2016"),
                  c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2),
                  c(149, 150, 151, 152, 155, 84, 83, 80, 81, 97),
                  c(101, 102, 104, 107, 99, 55, 55, 56, 57, 58),
                  c("MTL", "MTL", "MTL", "MTL", "MTL", "NY", "NY", 
                    "NY", "NY", "NY"))
colnames(DF1) <- c("date", "id", "sales", "cost", "city")

我想使用查找表添加上面显示的列name

   id  name start_date   end_date status
1:  1 Bank1 06/19/2016 06/25/2016      0
2:  2 Bank2 06/27/2016 06/27/2017      0
3:  3 Bank3 06/22/2016 06/24/2017      1
4:  4 Bank3 06/23/2016 12/23/2016      1

lookup <- data.table(c(1, 2, 3, 4),
                     c("Bank1", "Bank2", "Bank3", "Bank3"),
                     c("06/19/2016", "06/27/2016", "06/22/2016", "06/23/2016"),
                     c("06/25/2016", "06/27/2017", "06/24/2017", "12/23/2016"),
                     c("0", "0", "1", "1"))
colnames(lookup) <- c("id", "name", "start_date", "end_date", "status")

在这种情况下,我会使用 id 来查找名称。当我尝试merge 时,我总是在 DF1 中有包含 NA 的新行。

【问题讨论】:

  • 对于您的查找,您是否需要开始和结束日期和状态,或者是 id 和 name 足够的列?
  • id 和 name 是足够的列,但在运行脚本之前我不知道所有列,但我确信我们会有一个列 id 和一个列日期。
  • 仅供参考,您应该使用setnames 通过引用添加名称。
  • 无论如何,我认为你可以/应该这样做DF1[lookup, on="id", name := i.name]
  • @MaxMolina 这是在 j 中执行 x[i, on=, j] 时可用的特殊语法,该语法在您键入 ?data.table 时弹出的文档中的 j 参数下提到。还有一个x. 前缀。在这种情况下,确保我们从i=lookup 中提取列而不是从x=DF1 中已经存在的列name 中提取列是很有用的。这里有更多关于这种语法如何有用的信息:stackoverflow.com/q/54312225

标签: r data.table lookup vlookup


【解决方案1】:
DF1<-merge(DF1, lookup[,.(id, name)], by='id', all.x=TRUE, all.y=FALSE)

我认为合并命令是您在这里寻找的,但是您缺少 all.y = FALSE 位。我们在这里所做的是将 DF1 与查找数据表合并,我们告诉 R 包括 x 中的所有行,但只有 y 中的行与 x 中的行匹配,其中 x 是 DF1,y 是查找。 lookup[,.(id, name)] 意味着我们只想要列 id(与 DF1 匹配)和列 'name'。如果 DF1 中有在查找中没有匹配行的行,它们将显示为 NA,因为 all.x=TRUE。

【讨论】:

  • 如果我输入allow.cartesian = TRUE,当初始行数为83428时,我将有145368行。
  • 当我复制并粘贴您的前两个代码段以及我的答案时,它适用于我。你愿意在这里分享你的实际代码吗?你有没有在 library(data.table) 之后运行我的合并命令?
  • 它也对我有用,但是当我尝试使用我的真实数据集时,我得到了这个错误
  • 是否存在两个银行名称共享一个id的情况?
  • 如果您的查找表有一行 id: 2 和 name: BANK2 和另一行 id:2 和 name: bank2 那么你会得到你的错误。如果这是问题所在,您应该清理您的数据。我会用 x
【解决方案2】:

这是一个稍微不同的设置:我假设 id 对于两个数据集都是唯一的,并且查找数据包含主数据集中存在的所有 id。

我只查找 id 和 name 的子集。为了确保查找中没有重复(多个日期),我使用unique

DF1[unique(lookup[, .(id, name)]), on="id"][!is.na(sales)]

    id       date sales cost city  name
 1:  1 06/19/2016   149  101  MTL Bank1
 2:  1 06/20/2016   150  102  MTL Bank1
 3:  1 06/21/2016   151  104  MTL Bank1
 4:  1 06/22/2016   152  107  MTL Bank1
 5:  1 06/23/2016   155   99  MTL Bank1
 6:  2 06/19/2016    84   55   NY Bank2
 7:  2 06/20/2016    83   55   NY Bank2
 8:  2 06/21/2016    80   56   NY Bank2
 9:  2 06/22/2016    81   57   NY Bank2
10:  2 06/23/2016    97   58   NY Bank2

这称为左连接。我在最后使用 [!is.na()] 删除在主数据集中没有观察的银行 3 和 4。

【讨论】:

  • 谢谢。通过使用您的部分解决方案和@Austin 的解决方案,我能够得到我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-15
  • 2014-10-19
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
相关资源
最近更新 更多