R 数据表映射
我需要在一个大型(数百万行)数据集上进行批量重新映射 样本数据:R 数据表映射,r,mapping,data.table,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
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
我想用DTmap中的映射来映射DT中的a1列和a2列。忽略它们只是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
设置键(DT,a1)
设置键(DTmap,a1)
DT.merge1您可以使用
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
特别是在连接多个柱时,第二种方法更容易
要删除
a1
和a2
列,只需添加[,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
另一方面:当使用随机值生成器(如
sample
或rnorm
)提供样本数据时,最好使用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)
完美的正是我想要的,明白了。下次我将使用set.seed()。在第一次加入@Frank的解决方案时,为什么要使用i.b?它只与b一起工作。第二次,我明白了,因为否则它将是一个重复的列。@JesseBlocherI.
前缀指的是I
中的列;基本上,i
用于指定要使用索引向量或参考数据表选择哪些行(有关i
的更多信息,请参阅其含义)