2013-04-24 16 views
7

I dati provengono da un'altra domanda stavo giocando intorno con:data.table e tavolo comportamento imprevisto

dt <- data.table(user=c(rep(3, 5), rep(4, 5)), 
       country=c(rep(1,4),rep(2,6)), 
       event=1:10, key="user") 
# user country event 
#1:  3  1  1 
#2:  3  1  2 
#3:  3  1  3 
#4:  3  1  4 
#5:  3  2  5 
#6:  4  2  6 
#7:  4  2  7 
#8:  4  2  8 
#9:  4  2  9 
#10: 4  2 10 

Ed ecco il comportamento sorprendente:

dt[user == 3, as.data.frame(table(country))] 
# country Freq 
#1  1 4 
#2  2 1 

dt[user == 4, as.data.frame(table(country))] 
# country Freq 
#1  2 5 

dt[, as.data.frame(table(country)), by = user] 
# user country Freq 
#1: 3  1 4 
#2: 3  2 1 
#3: 4  1 5 
#    ^^^ - why is this 1 instead of 2?! 

Grazie mnel e Victor K. Il naturale il follow-up è - non dovrebbe essere 2, cioè questo è un bug? Mi aspettavo

dt[, blah, by = user] 

per tornare risultato identico a

rbind(dt[user == 3, blah], dt[user == 4, blah]) 

è questa aspettativa non è corretto?

+2

Il paese è in as.data.frame (tabella (paese)) un fattore? Se è così, è perché i livelli non sono gli stessi in entrambi. – mnel

+1

@mnel, mentre tu hai ragione nel fatto che è dovuto alla forzatura di 'as.data.frame' a' factor', il comportamento previsto sarebbe che il valore rappresentasse l'etichetta. Penso che questa sia probabilmente la stessa cosa che succede con 'rbindlist': http://stackoverflow.com/questions/15933846/rbindlist-two-data-tables-where-ha-fatt-factor-and-other-has- carattere-tipo-per/15935715 # 15935715 –

+0

@eddi, vedere l'aggiornamento alla mia risposta. –

risposta

5

As mnel come indicato nei commenti, as.data.frame(table(...)) produce un frame di dati in cui la prima variabile è un fattore. Per user == 4, c'è solo un livello nel fattore, che è memorizzato internamente come 1.

Quello che vuoi è fattore livelli, ma quello che si ottiene è come fattori vengono memorizzati internamente (come numeri interi, a partire dal 1) . Ciò che segue fornisce il risultato previsto:

> dt[, lapply(as.data.frame(table(country)), as.character), by = user] 
    user country Freq 
1: 3  1 4 
2: 3  2 1 
3: 4  2 5 

Aggiornamento. Per quanto riguarda la tua seconda domanda: no, penso che il comportamento di data.table sia corretto. Stessa cosa accade in pianura R quando si uniscono due fattori con diversi livelli:

> a <- factor(3:5) 
> b <- factor(6:8) 
> a 
[1] 3 4 5 
Levels: 3 4 5 
> b 
[1] 6 7 8 
Levels: 6 7 8 
> c(a,b) 
[1] 1 2 3 1 2 3 
+1

Come nota di interesse' dt [, lapply (as.data.frame.table (country), as.character), di = utente] 'dà un errore –

+1

Ma questo probabilmente non ha nulla a che fare con' data.table': ad esempio 'as.data.frame.table (dt $ country)' produce lo stesso errore –

+0

Questo è un buon punto –

7

L'approccio data.table idiomatica è quello di utilizzare .N

dt[ , .N, by = list(user, country)] 

Questo sarà molto più veloce ed è inoltre conserverà paese come la stessa classe dell'originale.

+0

nice one, thanks – eddi

Problemi correlati