r - 数据表映射

标签 r mapping data.table

我需要对大型(数百万行)数据集进行批量重新映射。

示例数据:

DT = data.table(yr = sample(3)+2000, a1 = sample(12), a2 = sample(12))[order(yr)]
DT
      yr a1 a2
 1: 2001  2  8
 2: 2001  3 12
 3: 2001 10  4
 4: 2001  9  6
 5: 2002  7  7
 6: 2002 11  3
 7: 2002  5  2
 8: 2002  1 11
 9: 2003  8  5
10: 2003 12  1
11: 2003  6  9
12: 2003  4 10

DTmap = data.table(a1 = 1:12, b=10001:10012)
DTmap
    a1     b
 1:  1 10001
 2:  2 10002
 3:  3 10003
 4:  4 10004
 5:  5 10005
 6:  6 10006
 7:  7 10007
 8:  8 10008
 9:  9 10009
10: 10 10010
11: 11 10011
12: 12 10012

我想将 DT 中的 a1 和 a2 列与 DTmap 中的映射进行映射。忽略它们只有 10000 个不同的事实 - 这是样本数据的产物,可以轻松检查结果的准确性。 我可以通过一系列连接来做到这一点,如下所示:

setkey(DT,a1)
setkey(DTmap,a1)
DT.merge1 <- DT[DTmap]

setkey(DT.merge1,a2)
setnames(DTmap,c("a2","b"))
setkey(DTmap,a2)

DT.merge2 <- DT.merge1[DTmap]
DT.merge2
      yr a1 a2     b   i.b
 1: 2003 12  1 10012 10001
 2: 2002  5  2 10005 10002
 3: 2002 11  3 10011 10003
 4: 2001 10  4 10010 10004
 5: 2003  8  5 10008 10005
 6: 2001  9  6 10009 10006
 7: 2002  7  7 10007 10007
 8: 2001  2  8 10002 10008
 9: 2003  6  9 10006 10009
10: 2003  4 10 10004 10010
11: 2002  1 11 10001 10011
12: 2001  3 12 10003 10012

DT.merge2[, `:=` (a1 = NULL, a2 = NULL)]
setnames(DT.merge2,c("year","b1","b2"))
DT.merge2
    year    b1    b2
 1: 2003 10012 10001
 2: 2002 10005 10002
 3: 2002 10011 10003
 4: 2001 10010 10004
 5: 2003 10008 10005
 6: 2001 10009 10006
 7: 2002 10007 10007
 8: 2001 10002 10008
 9: 2003 10006 10009
10: 2003 10004 10010
11: 2002 10001 10011
12: 2001 10003 10012

似乎有一种方法可以在 data.table 语法中使用 by() 或其他方法来做到这一点,但我无法弄清楚。我是一个相当新的 R 程序员,但在其他语言方面拥有丰富的经验。 这可能吗?上面的代码相对较快,但是有多种编码(通过 setkey)。看起来,使用 by() 和索引然后通过引用更新这些值会快得多。

最佳答案

您可以使用 match 来实现:

DT[, `:=` (b1 = DTmap$b[match(a1,DTmap$a1)], b2 = DTmap$b[match(a2,DTmap$a1)])]

或者按照@Frank的建议:

DT[DTmap, on = .(a1), b1 := i.b][DTmap, on = .(a2=a1), b2 := i.b]

使用这两种方法你会得到:

> DT
      yr a1 a2    b1    b2
 1: 2001  7  8 10007 10008
 2: 2001  4 11 10004 10011
 3: 2001  6 12 10006 10012
 4: 2001  8  2 10008 10002
 5: 2002 11  9 10011 10009
 6: 2002  9  5 10009 10005
 7: 2002 10  4 10010 10004
 8: 2002  2 10 10002 10010
 9: 2003 12  7 10012 10007
10: 2003  3  1 10003 10001
11: 2003  5  3 10005 10003
12: 2003  1  6 10001 10006

特别是在连接多个列时,第二种方法要容易得多。


要删除 a1a2 列,只需添加 [, c('a1','a2') := NULL] ,例如:

DT[, `:=` (b1 = DTmap$b[match(a1,DTmap$a1)], b2 = DTmap$b[match(a2,DTmap$a1)])
   ][, c('a1','a2') := NULL]

然后你将得到:

> DT
      yr    b1    b2
 1: 2001 10007 10008
 2: 2001 10004 10011
 3: 2001 10006 10012
 4: 2001 10008 10002
 5: 2002 10011 10009
 6: 2002 10009 10005
 7: 2002 10010 10004
 8: 2002 10002 10010
 9: 2003 10012 10007
10: 2003 10003 10001
11: 2003 10005 10003
12: 2003 10001 10006

旁注:当使用随机值生成器(例如 samplernorm)提供样本数据时,最好使用 set.seed().

使用的数据:

set.seed(2004)
DT = data.table(yr = sample(3)+2000, a1 = sample(12), a2 = sample(12))[order(yr)]
DTmap = data.table(a1 = 1:12, b=10001:10012)

关于r - 数据表映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43523719/

相关文章:

r - 将向量分割成 block ,使得每个 block 的总和近似恒定

r - R 函数内部赋值运算符 ('=' 和 '<-' 的行为

java - 将双向实体方法与 Mapstruct 结合使用

java - 从 List<String> 创建 HashMap

r - 仅通过 2 列键的第 2 列对 data.table 进行子集,使用二进制搜索而不是矢量扫描

javascript - 如何在 R highcharter 中制作 3 级钻取图(可能有其他包)

r - knitr 图制作了两次(使用 R 3.0.0)

python-3.x - 使用 pandas 数据帧映射到来自交通(节点)点的交通容量请求

r - 将唯一值拆分为多列的单独列

r - 计算满足日期条件后的行数