2013-04-13 13 views
13

Mi piacerebbe tracciare ogni colonna di un dataframe su un livello separato in ggplot2. Costruire lo strato dopo strato plot funziona bene:come aggiungere layer in ggplot usando un ciclo for-

df<-data.frame(x1=c(1:5),y1=c(2.0,5.4,7.1,4.6,5.0),y2=c(0.4,9.4,2.9,5.4,1.1),y3=c(2.4,6.6,8.1,5.6,6.3)) 

ggplot(data=df,aes(df[,1]))+geom_line(aes(y=df[,2]))+geom_line(aes(y=df[,3])) 

Esiste un modo per tracciare tutte le colonne disponibili presso quelli utilizzando una singola funzione?

ho cercato di fare in questo modo, ma non funziona:

plotAllLayers<-function(df){ 
    p<-ggplot(data=df,aes(df[,1])) 
    for(i in seq(2:ncol(df))){ 
     p<-p+geom_line(aes(y=df[,i])) 
     } 
     return(p) 
    } 

plotAllLayers(df) 

risposta

13

Un approccio potrebbe essere quello di rimodellare il frame di dati dal formato di larghezza in formato lungo usando la funzione melt() dalla libreria reshape2. Nel nuovo frame di dati saranno disponibili i valori x1, variable che determinano da quali dati di colonna è venuto e value che contiene tutti i valori y originali.

Ora è possibile tracciare tutti i dati con una chiamata ggplot() e geom_line() e utilizzare variable per disporre ad esempio del colore separato per ogni riga.

library(reshape2) 
df.long<-melt(df,id.vars="x1") 
head(df.long) 
    x1 variable value 
1 1  y1 2.0 
2 2  y1 5.4 
3 3  y1 7.1 
4 4  y1 4.6 
5 5  y1 5.0 
6 1  y2 0.4 
ggplot(df.long,aes(x1,value,color=variable))+geom_line() 

enter image description here

Se davvero si desidera utilizzare per() loop (non il modo migliore) quindi si dovrebbe utilizzare names(df)[-1] invece di seq(). Questo renderà il vettore dei nomi delle colonne (eccetto la prima colonna). Quindi all'interno di geom_line() utilizzare aes_string(y=i) per selezionare la colonna in base al nome.

plotAllLayers<-function(df){ 
    p<-ggplot(data=df,aes(df[,1])) 
    for(i in names(df)[-1]){ 
    p<-p+geom_line(aes_string(y=i)) 
    } 
    return(p) 
} 

plotAllLayers(df) 

enter image description here

+0

Grazie, questo risponde alla mia domanda. Aiuta davvero. reshape2 è molto utile. Immagino di dovermi abituare al formato lungo. – new2R

5

Ho provato il metodo di fusione su un grande insieme di dati disordinato e voluto per un metodo più veloce più pulito. Questo ciclo utilizza eval() per costruire la trama desiderata.

fields <- names(df_normal) # index, var1, var2, var3, ... 

p <- ggplot(aes(x=index), data = df_normal) 
for (i in 2:length(fields)) { 
    loop_input = paste("geom_smooth(aes(y=",fields[i],",color='",fields[i],"'))", sep="") 
    p <- p + eval(parse(text=loop_input)) 
} 
p <- p + guides(color = guide_legend(title = "",)) 
p 

Questo è stato eseguito molto più velocemente di un grande insieme di dati fuso quando ho provato.

Ho anche provato il ciclo for con il metodo aes_string (y = fields [i], color = fields [i]), ma non sono riuscito a differenziare i colori.

+1

L'unica risposta a questa domanda che ho visto è che scorre davvero e funziona davvero. Certo, molti considerano "eval" un peccato capitale, ma esiste per una ragione: p – ttbek