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?
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
@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
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