2012-06-08 21 views
10

Così, ho un frame di dati con due fattori e una variabile numerica in questo modo:movimentazione combinazioni di fattori mancanti in R

>D 
f1 f2 v1 
1 A 23 
2 A 45 
2 B 27 
    . 
    . 
    . 

così i livelli di f1 sono 1 e 2 e dei livelli di f2 sono A e B. Ecco la cosa, non c'è valore immesso per quando f1 = 1 e f2 = B (cioè D $ V1 [D $ f1 = 1 & D $ f2 = B] non c'è) in realtà questo dovrebbe essere zero.

Nel mio attuale quadro dati ho 11 livelli di f1 e quasi 150 livelli di f2 e ho bisogno di creare un'osservazione con v1 = 0 per ogni combinazione di f1 e f2 che manca nel mio frame di dati.

Come faccio a fare questo?

Grazie in anticipo,

Ian

risposta

11

Utilizzando i dati:

dat <- data.frame(f1 = factor(c(1,2,2)), f2 = factor(c("A","A","B")), 
        v1 = c(23,45,27)) 

una possibilità è quella di creare una tabella di ricerca con le combinazioni di livelli, che è fatto usando la funzione expand.grid() in dotazione con i livelli di entrambi i fattori, come mostrato di seguito:

dat2 <- with(dat, expand.grid(f1 = levels(f1), f2 = levels(f2))) 

Un database simile join operazione può essere effettuata utilizzando la funzione merge() in cui si precisa che tutti i valori della tabella di ricerca sono inclusi nel join (all.y = TRUE)

newdat <- merge(dat, dat2, all.y = TRUE) 

La riga precedente produce:

> newdat 
    f1 f2 v1 
1 1 A 23 
2 1 B NA 
3 2 A 45 
4 2 B 27 

Come si può vedere, le combinazioni mancanti hanno il valore NA che indica la mancanza. E 'realtively semplice per poi sostituire questi NA s con 0 s:

> newdat$v1[is.na(newdat$v1)] <- 0 
> newdat 
    f1 f2 v1 
1 1 A 23 
2 1 B 0 
3 2 A 45 
4 2 B 27 
+0

@ user1443010 in quella linea, lo sto usando per evitare 'dat $ f1' e' dat $ f2'. Penso anche che chiarisca l'intenzione; usando * questo * oggetto, fai * quello *. Non c'è nulla di sbagliato in questo a livello di utente, ma c'è una penalità di efficienza in quanto R deve creare un nuovo ambiente con i contenuti dell'oggetto e richiede tempo. 'dat2 <- expand.grid (f1 = levels (dat $ f1), f2 = levels (dat $ f2))' sarebbe l'alternativa. Non puoi sempre lavorare le cose in un 'with()'; Non penso che la linea che sostituisce 'NA' possa essere facilmente trasformata in' with() ', ma potrei mancare qualcosa. –

+0

fantastico! Grazie! ;) – maycca

1

due anni di ritardo, ma ho avuto lo stesso problema e si avvicinò con questa soluzione plyr:

dat <- data.frame(f1 = factor(c(1,2,2)), f2 = factor(c("A","A","B")), v1 = c(23,45,27)) 

newdat <- ddply(dat, .(f1,f2), numcolwise(function(x) {if(length(x)>0) x else 0.0}), .drop=F) 

> newdat 
    f1 f2 v1 
1 1 A 23 
2 1 B 0 
3 2 A 45 
4 2 B 27 
2

aggiungo il tidyr soluzione, diffondendo con fill=0 e raccolta.

library(tidyr) 
df %>% spread(f2, v1, fill=0) %>% gather(f2, v1, -f1) 

# f1 f2 v1 
#1 1 A 23 
#2 2 A 45 
#3 1 B 0 
#4 2 B 27 

Si potrebbe ugualmente fare df %>% spread(f1, v1, fill=0) %>% gather(f1, v1, -f2).