2016-01-16 16 views
17

L'argomento drop in dcast (da "reshape2" o "dplyr") può essere utile quando si passa da "lungo" a "ampio" "set di dati e vuoi creare colonne anche per combinazioni che non esistono nel formato lungo.Effettuare l'argomento `drop` in` dcast` solo guardare l'RHS della formula

Si scopre che utilizzando drop influisce anche le combinazioni sul lato sinistro (LHS) della formula e sul lato destro (RHS). Pertanto, crea anche righe in base alle combinazioni di valori LHS.

C'è un modo per ignorare questo comportamento?


Ecco alcuni dati di esempio:

library(data.table) 
DT <- data.table(v1 = c(1.105, 1.105, 1.105, 2.012, 2.012, 2.012), 
       ID = c(1L, 1L, 1L, 2L, 2L, 2L), 
       v2 = structure(c(2L, 3L, 5L, 1L, 2L, 6L), 
           .Label = c("1", "2", "3", "4", "5", "6"), 
           class = "factor"), 
       v3 = c(3L, 2L, 2L, 5L, 4L, 3L)) 

Si noti che "v2" è una colonna factor con 6 livelli. Io essenzialmente voglio andare da "lungo" alla larga", ma aggiungere colonne per eventuali livelli di fattore mancante (in questo caso '4')

reshape gestisce la forma, ma non le colonne mancanti:.

reshape(DT, direction = "wide", idvar = c("ID", "v1"), timevar = "v2") 
#  v1 ID v3.2 v3.3 v3.5 v3.1 v3.6 
# 1: 1.105 1 3 2 2 NA NA 
# 2: 2.012 2 4 NA NA 5 3 

dcast maniglie aggiungendo le colonne mancanti, ma solo se c'è un valore sul lato sinistro:

dcast(DT, ID ~ v2, value.var = "v3", drop = FALSE) 
# ID 1 2 3 4 5 6 
# 1: 1 NA 3 2 NA 2 NA 
# 2: 2 5 4 NA NA NA 3 

Se non ci sono più valori sul lato sinistro, le combinazioni dei valori sul lato sinistro sono anche ampliato, come se avessimo usato CJ o expand.grid, ma righe 2 e 3 non sono affatto interessare me:

dcast(DT, ... ~ v2, value.var = "v3", drop = FALSE) 
#  v1 ID 1 2 3 4 5 6 
# 1: 1.105 1 NA 3 2 NA 2 NA 
# 2: 1.105 2 NA NA NA NA NA NA 
# 3: 2.012 1 NA NA NA NA NA NA 
# 4: 2.012 2 5 4 NA NA NA 3 

Questo è simile all'utilizzo xtabs a base di R: ftable(xtabs(v3 ~ ID + v1 + v2, DT)).


C'è un modo per far sapere che dcast essenzialmente, "Hey. La combinazione di valori sul lato sinistro sono gli ID. Non cercare di riempire loro in me."

Il mio attuale approccio consiste nel fare tre passaggi, uno per il collasso dei valori LHS, un altro per la diffusione dei valori RHS e uno per la fusione del risultato.

merge(DT[, list(v1 = unique(v1)), .(ID)], ## or unique(DT[, c("ID", "v1"), with = FALSE]) 
     dcast(DT, ID ~ v2, value.var = "v3", drop = FALSE), 
     by = "ID")[] 
# ID v1 1 2 3 4 5 6 
# 1: 1 1.105 NA 3 2 NA 2 NA 
# 2: 2 2.012 5 4 NA NA NA 3 

C'è un approccio migliore che mi manca?

+0

qualcosa di simile (forse): 'dcast (DT, interazione (v1, ID, goccia = TRUE) ~ v2, value.var = "v3", goccia = FALSE)'. Devi dividere la prima colonna dopo, comunque. – nicola

+0

@nicola, ci ho pensato, ma non mi piaceva l'eventuale perdita di fedeltà dei dati, la mancanza dell'opzione di usare '...' sul LHS e la perdita dei nomi delle colonne. – A5C1D2H2I1M1N2O1R2T1

+0

Una possibile soluzione potrebbe consentire un doppio logico in 'drop'. Qualcosa come 'drop = c (TRUE, FALSE)' dove la prima si applica a RHS e la seconda a LHS. – Jaap

risposta

7

Appena implementato nella versione di sviluppo data.table v1.9.7, commit 2113, chiude #1512.

require(data.table) # v1.9.7, commit 2113+ 
dcast(DT, ... ~ v2, value.var = "v3", drop = c(TRUE, FALSE)) 
#  v1 ID 1 2 3 4 5 6 
# 1: 1.105 1 NA 3 2 NA 2 NA 
# 2: 2.012 2 5 4 NA NA NA 3