2013-02-25 2 views
7

Ho questo problema con data.table che mi sta facendo impazzire di recente. Sembra un bug ma potrebbe essermi perso qualcosa di ovvio qui.data.table NON riepilogando correttamente da due colonne

Ho la seguente struttura dei dati:

# First some data 
data <- data.table(structure(list(
    month = structure(c(1356998400, 1356998400, 1356998400, 
         1359676800, 1354320000, 1359676800, 1359676800, 1356998400, 1356998400, 
         1354320000, 1354320000, 1354320000, 1359676800, 1359676800, 1359676800, 
         1356998400, 1359676800, 1359676800, 1356998400, 1359676800, 1359676800, 
         1359676800, 1359676800, 1354320000, 1354320000), class = c("POSIXct", 
                       "POSIXt"), tzone = "UTC"), 
    portal = c(TRUE, TRUE, FALSE, TRUE, 
      TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, 
      TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE 
), 
    satisfaction = c(10L, 10L, 10L, 9L, 10L, 10L, 9L, 10L, 10L, 
        9L, 2L, 8L, 10L, 9L, 10L, 10L, 9L, 10L, 10L, 10L, 9L, 10L, 9L, 
        10L, 10L)), 
        .Names = c("month", "portal", "satisfaction"), 
        row.names = c(NA, -25L), class = "data.frame")) 

voglio riassumere esso sia portal e month. Riassumendo con il buon vecchio tapply opere come previsto - ho matrice 3x2 con i risultati per Dic-2012 e gennaio-febbraio 2013:

> tapply(data$satisfaction, list(data$month, data$portal), mean) 
      FALSE  TRUE 
2012-12-01 8.5 8.000000 
2013-01-01 10.0 10.000000 
2013-02-01 9.0 9.545455 

Riassumendo con by argomento data.table non lo fa:

> data[, mean(satisfaction), by = 'month,portal'] 
    month  portal  V1 
1: 2013-01-01 FALSE 10.000000 
2: 2013-02-01 TRUE 9.000000 
3: 2013-01-01 TRUE 10.000000 
4: 2012-12-01 FALSE 8.500000 
5: 2012-12-01 TRUE 7.333333 
6: 2013-02-01 TRUE 9.666667 
7: 2013-02-01 FALSE 9.000000 
8: 2012-12-01 TRUE 10.000000 

Come si vedere, restituisce una tabella di dati con valori , non come previsto; valori dove portal == TRUE e month == 2012-02-01 sono duplicati, per esempio.

È interessante notare che, se mi limito dati questo solo per 2013 di, tutto funziona come previsto:

> data[month >= ymd(20130101), mean(satisfaction), by = 'month,portal'] 
     month portal  V1 
1: 2013-01-01 TRUE 10.000000 
2: 2013-01-01 FALSE 10.000000 
3: 2013-02-01 TRUE 9.545455 
4: 2013-02-01 FALSE 9.000000 

Sono perplesso di là credo :). Qualcuno potrebbe aiutarmi?

+0

Utilizzare 'by = list (month, portal)' – Andrie

+0

In primo luogo, 'data [, mean (soddisfazione), per = list (mese, portale)]' produce lo stesso risultato (errato). In secondo luogo, secondo l'aiuto di 'data.table', sono supportate entrambe le sintassi:" by - Un singolo nome di colonna non quotato, un elenco() di espressioni di nomi di colonne, una stringa di singolo carattere contenente i nomi di colonna separati da virgola o un vettore di carattere di nomi di colonne." –

+3

La conversione della colonna POSIX in data (' as.Date') sembra funzionare.Penso che data.table sia (correttamente? Erroneamente?) Dividendo alcuni capelli se alcune di quelle date sono "uguali". – joran

risposta

8

Questo è un problema noto risolto in data.table 1.8.7 (non ancora in CRAN al momento della stesura di questo documento).

Da data.table NEWS:

BUG FIXES 

    <...> 

o setkey could sort 'double' columns (such as POSIXct) incorrectly when not the 
    last column of the key, #2484. In data.table's C code : 
     x[a] > x[b]-tol 
    should have been : 
     x[a]-x[b] > -tol [or x[b]-x[a] < tol ] 
    The difference may have been machine/compiler dependent. Many thanks to statquant 
    for the short reproducible example. Test added. 

Dopo l'aggiornamento a 1.8.7 con install.packages("data.table", repos="http://R-Forge.R-project.org"), tutto funziona come previsto.

5

Il problema sembra essere con l'ordinamento. Quando carico data e fare setkey:

setkey(data, "month", "portal") 

# > data 
#   month portal satisfaction 
# 1: 2012-12-01 TRUE   10 
# 2: 2012-12-01 FALSE   9 
# 3: 2012-12-01 FALSE   8 
# 4: 2012-12-01 TRUE   2 
# 5: 2012-12-01 TRUE   10 
# 6: 2012-12-01 TRUE   10 
# 7: 2013-01-01 TRUE   10 
# 8: 2013-01-01 TRUE   10 
# 9: 2013-01-01 TRUE   10 
# 10: 2013-01-01 TRUE   10 
# 11: 2013-01-01 TRUE   10 
# 12: 2013-01-01 TRUE   10 
# 13: 2013-01-01 FALSE   10 
# 14: 2013-02-01 TRUE   9 
# 15: 2013-02-01 TRUE   9 
# 16: 2013-02-01 FALSE   9 
# 17: 2013-02-01 TRUE   10 
# 18: 2013-02-01 TRUE   10 
# 19: 2013-02-01 TRUE   10 
# 20: 2013-02-01 TRUE   10 
# 21: 2013-02-01 TRUE   10 
# 22: 2013-02-01 TRUE   9 
# 23: 2013-02-01 TRUE   10 
# 24: 2013-02-01 TRUE   9 
# 25: 2013-02-01 TRUE   9 
#   month portal satisfaction 

Si vede che la colonna portal non è correttamente allineati. Quando faccio setkey di nuovo,

setkey(data, "month", "portal") 

# I get this warning message: 
Warning message: 
In setkeyv(x, cols, verbose = verbose) : 
    Already keyed by this key but had invalid row order, key rebuilt. 
    If you didn't go under the hood please let datatable-help know so 
    the root cause can be fixed. 

Ora, i data colonne sembrano adeguatamente ordinate per le colonne chiave:

# > data 
#   month portal satisfaction 
# 1: 2012-12-01 FALSE   9 
# 2: 2012-12-01 FALSE   8 
# 3: 2012-12-01 TRUE   10 
# 4: 2012-12-01 TRUE   2 
# 5: 2012-12-01 TRUE   10 
# 6: 2012-12-01 TRUE   10 
# 7: 2013-01-01 FALSE   10 
# 8: 2013-01-01 TRUE   10 
# 9: 2013-01-01 TRUE   10 
# 10: 2013-01-01 TRUE   10 
# 11: 2013-01-01 TRUE   10 
# 12: 2013-01-01 TRUE   10 
# 13: 2013-01-01 TRUE   10 
# 14: 2013-02-01 FALSE   9 
# 15: 2013-02-01 TRUE   9 
# 16: 2013-02-01 TRUE   9 
# 17: 2013-02-01 TRUE   10 
# 18: 2013-02-01 TRUE   10 
# 19: 2013-02-01 TRUE   10 
# 20: 2013-02-01 TRUE   10 
# 21: 2013-02-01 TRUE   10 
# 22: 2013-02-01 TRUE   9 
# 23: 2013-02-01 TRUE   10 
# 24: 2013-02-01 TRUE   9 
# 25: 2013-02-01 TRUE   9 
#   month portal satisfaction 

Così, sembra essere un problema con un sortting POSIXct + logical tipi?

data[, mean(satisfaction), by=list(month, portal)] 

#   month portal  V1 
# 1: 2012-12-01 FALSE 8.500000 
# 2: 2012-12-01 TRUE 8.000000 
# 3: 2013-01-01 FALSE 10.000000 
# 4: 2013-01-01 TRUE 10.000000 
# 5: 2013-02-01 FALSE 9.000000 
# 6: 2013-02-01 TRUE 9.545455 

Penso quindi che ci sia un bug.

+2

Sì, stavo proprio per lasciare un commento che diceva che se @MatthewDowle non ha un peso in questo giorno o due, l'OP dovrebbe probabilmente postare questa domanda sulla mailing list data.table. – joran

+1

Aha! Grazie Arun, sembra proprio che sia così. Lo segnalerò come un bug alla mailing list. Aspetteremo che Matthew risponda nel caso in cui prima di accettare la tua risposta. –

+0

@joran, vincitore, certo. – Arun