2015-12-04 10 views
10

Zauważyłem pewne dziwne zachowanie danych.table, mam nadzieję, że ktoś, kto rozumie dane.tabel lepiej niż mogę wyjaśnić.data.table "list" versus ": =" w radzeniu sobie z NaN

Say mam ten 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 

Teraz, w moim umyśle, następujące dwie metody powinien wygenerować takie same wyniki, ale tak nie jest.

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 

Jak widać, przy użyciu ": =" wytwarza minimalną wartość (C1, C2 = b = c) 8. Zważywszy na wyniki poleceń listę w NaN. Co zabawne, dla (C1 = B, C2 = b) i (C1 = C, C2 = d), które również mają NaN, polecenie list generuje wartość. Uważam, że tak jest, ponieważ w przypadku, gdy NaN jest pierwszy przed wartością dla danej kombinacji C1 C2, wynik NaN. Podczas gdy w dwóch pozostałych przypadkach NaN występuje po wartości.

Dlaczego tak się dzieje?

Zauważam, że jeśli NAN zostaną zastąpione NA, wtedy wartości są generowane bez problemów.

+1

nie pomysł, ale 'DT [lista (dwumecz = min (.SD $ Val, na.rm = TRUE)), by = c ('C1', 'C2')]' działa również – rawr

+1

Or 'DT [, list (agg = min (c (Val), na.rm = TRUE)), by =. (C1, C2)]' To jest trochę dziwne, ale równoważny krok w 'dplyr' działa po konwersji do 'data.frame'. – akrun

+1

Zdecydowanie powinieneś zgłosić błąd. Podejrzewam, że jest to spowodowane "wewnętrzną" implementacją funkcji 'data.table'' min'. Wewnątrz operacji 'data.table' niektóre funkcje (jak' min', 'max' i' sum') są zastępowane przez szybsze wersje 'data.table'. Jeśli wywołasz jawnie funkcję 'base', otrzymasz poprawne wyjście:' DT [, list (agg = base :: min (Val, na.rm = TRUE)), by = c ('C1', 'C2')] '. Nie mam pojęcia, dlaczego 'data.table' wydaje się powracać do' base :: min' kiedy jest używane w połączeniu z ': ='. – nicola

Odpowiedz

7

Naprawiono ten problem, #1461 właśnie teraz w devel, v1.9.7 z 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