2013-04-13 3 views
13

Я хотел бы построить каждый столбец данных на отдельный слой в ggplot2. Строительство участка послойно хорошо работает:Как добавить слои в ggplot с помощью for-loop

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])) 

Есть ли способ, чтобы построить все доступные столбцы на них с помощью одной функции?

Я пытался сделать это таким образом, но это не работает:

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) 

ответ

13

Один подход должен был бы изменить свой кадр данных из широкого формата в длинном формате, используя функцию melt() из библиотеки reshape2. В новом фрейме данных вы будете иметь значения x1, variable, которые определяют, из каких данных столбца, и value, который содержит все исходные значения y.

Теперь вы можете построить все данные с помощью одного ggplot() и geom_line() позвонить и использовать variable, чтобы иметь, например, отдельный цвет для каждой строки.

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

Если вы действительно хотите использовать для() петли (не самый лучший способ), то вы должны использовать names(df)[-1] вместо seq(). Это сделает вектор имен столбцов (кроме первого столбца). Затем внутри geom_line() используйте aes_string(y=i) для выбора столбца по их названию.

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

Спасибо, это отвечает на мой вопрос. Это действительно помогает. reshape2 очень полезен. Я предполагаю, что мне нужно привыкнуть к длинному формату. – new2R

5

Я попробовал метод расплава на большой грязный набор данных и пожелал для более быстрой, более чистого метода. Для цикла for используется eval() для построения нужного графика.

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 

Это было намного быстрее, чем большой расплавленный набор данных, когда я тестировал.

Я также пробовал цикл for с помощью метода aes_string (y = fields [i], color = fields [i]), но не смог получить цвета для дифференциации.

+1

Единственный ответ на этот вопрос, который я видел, который действительно петли и на самом деле работает. Конечно, многие считают «eval» кардинальным грехом, но он существует по причине: P – ttbek

Смежные вопросы