将.BY与查找表一起使用 - 意外结果

时间:2013-02-27 20:21:48

标签: r data.table

我想根据查找表dtk中创建一个变量。我得到了一些意想不到的结果,这取决于我如何在k中提取感兴趣的变量。

dt <- data.table(x=c(1:10))
setkey(dt, x)

k <- data.table(x=c(1:5,10), b=c(letters[1:5], "d"))
setkey(k, x)

dt[,b:=k[.BY, list(b)],by=x]

dt  #unexpected results
#      x  b
#  1:  1  1
#  2:  2  2
#  3:  3  3
#  4:  4  4
#  5:  5  5
#  6:  6  6
#  7:  7  7
#  8:  8  8
#  9:  9  9
# 10: 10 10

dt <- data.table(x=c(1:10))
setkey(x, x)

dt[,b:=k[.BY]$b,by=x]

dt  #expected results
#      x  b
#  1:  1  a
#  2:  2  b
#  3:  3  c
#  4:  4  d
#  5:  5  e
#  6:  6 NA
#  7:  7 NA
#  8:  8 NA
#  9:  9 NA
# 10: 10  d

任何人都可以解释为什么会这样吗?

1 个答案:

答案 0 :(得分:3)

您根本不必使用by=.

第一个解决方案:

设置适当的密钥并使用data.table中的X [Y]语法:

require(data.table)
dt <- data.table(x=c(1:10))
setkey(dt, "x")
k <- data.table(x=c(1:5,10), b=c(letters[1:5], "d"))
setkey(k, "x")

k[dt]

#      x  b
#  1:  1  a
#  2:  2  b
#  3:  3  c
#  4:  4  d
#  5:  5  e
#  6:  6 NA
#  7:  7 NA
#  8:  8 NA
#  9:  9 NA
# 10: 10  d
OP表示这会创建一个新的data.table,这对他来说是不受欢迎的。

第二种解决方案

再次,没有by

dt <- data.table(x=c(1:10))
setkey(dt, "x")
k <- data.table(x=c(1:5,10), b=c(letters[1:5], "d"))
setkey(k, "x")

# solution
dt[k, b := i.b]

这不会创建新的data.table并提供您期望的解决方案。

解释意外结果发生的原因:

对于第一种情况dt[,b:=k[.BY, list(b)],by=x]。在这里,k[.BY, list(b)]本身会返回data.table。例如:

k[list(x=1), list(b)]

#    x b
# 1: 1 a

所以,基本上,如果你这样做:

k[list(x=dt$x), list(b)]

这也会为您提供所需的解决方案。为了回答为什么你得到b := k[.BY, list(b)]时获得的结果,因为RHS返回一个data.table并且你为它分配一个变量,它将获取第一个元素并删除其余元素。例如,执行以下操作:

dt[, c := dt[1], by=x] 
# you'll get the whole column to be 1

对于第二种情况,要理解其工作原理,您必须了解与data.table k[6]k[list(6)]之间的细微差别},例如:

在第一种情况下,k[6],您正在访问k的第6个元素,即10 d。但在第二种情况下,你要求J, join。因此,它搜索x = 6(键列),因为k中没有,它返回6 NA。在您的情况下,由于您使用返回列表的k[.BY],因此它是J操作,它会获取正确的值。

我希望这会有所帮助。