2013-02-22 8 views
7

Ho bisogno di riorganizzare i dati da un file CSV che contiene per lo più dati ripetuti. Ho i dati importati in R in un dataframe ma sto avendo problemi con il seguente:Riorganizzazione dei dati da 3 righe a 1

ID Language Author Keyword 
12 eng  Rob  COLOR=Red 
12 eng  Rob  SIZE=Large 
12 eng  Rob  DD=1 
15 eng  John  COLOR=Red 
15 eng  John  SIZE=Medium 
15 eng  John  DD=2 

Che cosa devo fare è trasformare questo in una riga con ogni parola chiave in una colonna separata

ID Language Author COLOR SIZE  DD 
12 eng  Rob  Red Large  1 

Qualche idea?

risposta

7

Usando il pacchetto reshape2 questo è semplice:

Con tt definito come in Gary's answer

library("reshape2") 

tt <- cbind(tt, colsplit(tt$Keyword, "=", c("Name", "Value"))) 
tt_new <- dcast(tt, ID + Language + Author ~ Name, value.var="Value") 

che dà

> tt_new 
    ID Language Author COLOR DD SIZE 
1 12  eng Rob Red 1 Large 
2 15  eng John Red 2 Medium 
+0

Sono in grado di farlo funzionare ma dopo l'esecuzione di dcast() viene visualizzato un errore che dice: Funzione di aggregazione mancante: default alla lunghezza. Quindi ottengo un 1 in ognuna delle nuove variabili. Immagino che nel set di dati reale ci debba essere qualcosa che non è giusto in quanto funziona bene con questo set di dati semplificato. Qualche idea? – Ray

+0

Sembra che abbia numeri ineguali da qualche parte. Hai bisogno di capire come trovare l'ID con più di 3 righe e pulirlo. – Ray

+0

Si otterrebbe questo avviso se c'è una combinazione di 'ID',' Lingua', 'Autore' e' Nome' che appare più di una volta. Puoi dire quale è/quelli che sono cercando un valore diverso da 1 nel risultato (in sostanza, quando ci sono più valori per una combinazione, la risagoma li aggregherà in un singolo valore in qualche modo, e per impostazione predefinita, che in qualche modo sta contando quanti ce ne sono). –

6

Utilizzando plyr ans strsplit si può fare qualcosa di simile:

library(plyr) 
res <- ddply(dat,.(ID,Language,Author),function(x){ 
     unlist(sapply(strsplit(x$Keyword,'='),'[',2)) 
}) 

colnames(res)[4:6] <- c('COLOR','SIZE','DD') 

ID Language Author COLOR SIZE DD 
1 12  eng Rob Red Large 1 
2 15  eng John Red Medium 2 

Edit: Ecco una generalizzazione che affronta @ preoccupazione di Brian:

res <- ddply(dat,.(ID,Language,Author), function(x){ 
      kv <- strsplit(x$Keyword, '=') 
      setNames(sapply(kv, `[`, 2), 
         sapply(kv, `[`, 1)) }) 
+0

sì, è più bella ;-) –

+2

Come punto di cautela, questo fa supponiamo che le parole chiave siano sempre 'COLOR',' SIZE' e 'DD' e sempre in questo ordine. Se questa ipotesi è vera, funziona bene. –

+0

@flodel grazie per l'elegante modifica. – agstudy

1

Prova questo utilizzando reshape2:

tt <- read.table(header=T,text='ID Language Author Keyword 
12 eng  Rob  COLOR=Red 
12 eng  Rob  SIZE=Large 
12 eng  Rob  DD=1 
15 eng  John  COLOR=Red 
15 eng  John  SIZE=Medium 
15 eng  John  DD=2') 

tt$Keyword <- as.character(tt$Keyword) 

tt <- transform(tt, key_val = lapply(tt$Keyword,function(x) strsplit(x,'=')[[1]][2]), 
key_var = lapply(tt$Keyword,function(x) strsplit(x,'=')[[1]][1])) 

tt_new <- dcast (tt, ID + Language + Author ~ key_var, value.var='key_val') 
+0

Sei sicuro che questo funzioni ..? – agstudy

+0

Il tuo 'lapply' dovrebbe essere' sapply''s e hai bisogno di un 'value.var =" key_val "' nella tua chiamata 'dcast'. –

+0

Non ho capito che 'value.var' aveva bisogno della var tra virgolette, quindi mi ha dato un errore. L'ho lasciato fuori ma 'dcast' ha indovinato la variabile giusta in questo caso. Grazie. –

Problemi correlati