2013-02-27 47 views
3

我想根據查找表kdt中創建一個變量。根據我在k中提取感興趣的變量,我得到了一些意想不到的結果。在查找表中使用.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) 

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 

任何人都可以解釋爲什麼會發生這種情況嗎?

回答

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個元素,即10 d。但在第二種情況下,您要求提供J, join。因此,它搜索x = 6(鍵列),並且由於k中沒有任何內容,所以它返回6 NA。在你的情況下,因爲你使用k[.BY]它返回一個列表,它是一個J操作,它獲取正確的值。

我希望這會有所幫助。

+0

這創建了一個我的方法避免的全新數據表。此外,我特別感興趣的是爲什麼結果取決於我如何從'k'中提取'b' – Michael 2013-02-27 20:27:46

+0

首先,'.BY'返回一個列表。所以,你必須訪問'k [.BY $ x,b]'。其實,你可以只用'k [x,b]'來訪問它。我正在弄清楚其他原因以及如何根據需要獲得解決方案。 – Arun 2013-02-27 20:35:47

+0

'k [x,b]',我相信在每個組中有大量行的情況下效率不高。 – Michael 2013-02-27 20:39:34