2013-04-13 1 views
13

Chciałbym wykreślić każdą kolumnę ramki danych na osobnej warstwie w ggplot2. Budowanie warstwa po warstwie fabuły działa dobrze:jak dodawać warstwy w ggplot używając pętli 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])) 

Czy istnieje sposób, aby wykreślić wszystkie dostępne kolumny z nich za pomocą pojedynczej funkcji?

starałem się zrobić to w ten sposób, ale to nie działa:

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) 

Odpowiedz

13

Jedno podejście byłoby zmienić kształt ramki danych z formatu szerokim i długim formacie za pomocą funkcji melt() z biblioteki reshape2. W nowej ramce danych będziesz mieć wartości x1, variable, które określają, z której kolumny pochodzą dane, i value, która zawiera wszystkie oryginalne wartości y.

Teraz możesz wykreślić wszystkie dane za pomocą jednego połączenia ggplot() i geom_line() i użyć na przykład oddzielnego koloru dla każdej linii.

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

Jeśli naprawdę chcesz używać do() pętli (nie jest to najlepszy sposób) należy użyć names(df)[-1] zamiast seq(). Spowoduje to utworzenie wektora nazw kolumn (z wyjątkiem pierwszej kolumny). Następnie wewnątrz geom_line() użyj aes_string(y=i), aby wybrać kolumnę według nazwy.

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

Dziękuję, to odpowiada na moje pytanie. To naprawdę pomaga. reshape2 jest bardzo przydatny. Sądzę, że muszę się przyzwyczaić do długiego formatu. – new2R

5

Próbowałem metody stopu na dużym zbiorze brudny i prosic o szybsze, czystsze metody. Ta pętla for używa eval() do zbudowania pożądanego wykresu.

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 

Podczas testu test ten przebiegał znacznie szybciej niż duży, przetopiony zbiór danych.

Próbowałem również pętli for z metodą aes_string (y = pola [i], kolor = pola [i]), ale nie mogłem uzyskać różnicowania kolorów.

+1

Jedyną odpowiedzią na to pytanie, które widziałem, jest naprawdę pętla i działa. Wiele osób uważa, że ​​"eval" jest grzechem kardynalnym, ale istnieje z jakiegoś powodu: P – ttbek