2015-12-04 50 views
10

注意到data.table有些奇怪的行爲,希望能理解data.table的人比我能解釋得更好。data.table「list」與「:=」在處理NaN時

說我有這個data.table:現在

library(data.table) 
DT <- data.table(
    C1 = c(rep("A", 4), rep("B",4), rep("C", 4)), 
    C2 = c(rep("a", 3), rep("b",3), rep("c",3), rep("d",3)), 
    Val = c(1:5, NaN, NaN, 8,9,10,NaN,12)) 

DT 
    C1 C2 Val 
1: A a 1 
2: A a 2 
3: A a 3 
4: A b 4 
5: B b 5 
6: B b NaN 
7: B c NaN 
8: B c 8 
9: C c 9 
10: C d 10 
11: C d NaN 
12: C d 12 

,在我的腦海中,以下兩種方法應該產生相同的結果,但他們沒有。

TEST1 <- DT[, agg := min(Val, na.rm = TRUE), by = c('C1', 'C2')] 
TEST1 <- data.table(unique(TEST1[, c('C1','C2','agg'), with = FALSE])) 

TEST2 <- DT[, list(agg = min(Val, na.rm = TRUE)), by = c('C1', 'C2')] 

TEST1 
    C1 C2 agg 
1: A a 1 
2: A b 4 
3: B b 5 
4: B c 8 
5: C c 9 
6: C d 10 


TEST2 
    C1 C2 agg 
1: A a 1 
2: A b 4 
3: B b 5 
4: B c NaN 
5: C c 9 
6: C d 10 

正如可以看到的,使用 「:=」 生成的8而在一個NaN的列表命令的結果(C1 = B,C2 = C)的最小值。有趣的是,對於(C1 = B,C2 = b)和(C1 = C,C2 = d),它們也有NaN,list命令確實產生了一個值。 我相信這是因爲在NaN首先出現在給定的C1 C2組合的值之前的情況下,結果是NaN。而在另外兩個例子中,NaN就是一個值。

爲什麼會發生這種情況?

我注意到,如果NaN被替換爲NA,那麼會生成沒有問題的值。

+1

不知道但'DT [,列表(AGG =分鐘(.SD $纈氨酸,na.rm = TRUE)),通過= C( 'C1', 'C2')]'也適用 – rawr

+1

或者'DT [,list(agg = min(c(Val),na.rm = TRUE)),by =。(C1,C2)]'這有點奇怪,但'dplyr'中的等價步驟在轉換後生效到'data.frame'。 – akrun

+1

你一定要報告一個錯誤。我懷疑這是由於'data.table''min'函數的「內部」實現引起的。在'data.table'操作中,一些函數(比如'min','max'和'sum')被更快的'data.table'版本取代。如果明確地調用'base'函數,則得到正確的輸出:'DT [,list(agg = base :: min(Val,na.rm = TRUE)),by = c('C1','C2' )]'。不知道爲什麼''data.table'似乎在與':='組合使用時會回覆到'base :: min'。 – nicola

回答

7

修正了這個問題,#1461剛剛在devel中,v1.9.7和commit 2080

require(data.table) # v1.9.7, commit 2080+ 
DT <- data.table(
    C1 = c(rep("A", 4), rep("B",4), rep("C", 4)), 
    C2 = c(rep("a", 3), rep("b",3), rep("c",3), rep("d",3)), 
    Val = c(1:5, NaN, NaN, 8,9,10,NaN,12)) 

DT[, list(agg = min(Val, na.rm = TRUE)), by = c('C1', 'C2')] 
# C1 C2 agg 
# 1: A a 1 
# 2: A b 4 
# 3: B b 5 
# 4: B c 8 
# 5: C c 9 
# 6: C d 10