ggplot2 labeling graphs in a loop

我们两清 提交于 2020-07-07 12:41:47

问题


I would like to put vertical lines and labels for the vertical lines for each graph in a loop. the position of the line is saved in a dataframe "grid".

Although the position of the line seems correct the label value and its position is off. My question is why.

    library(ggplot2)
    library(grid)
    library(gridExtra)
    
    
    plots <- list()
    
    grid <- data.frame(x=seq(4), y=c(200, 400, 600, 800))
    
    for (i in 1:4) {
      V1 <- rnorm(1000)
      V2 <- seq(1000)
      df <- data.frame(V1, V2)
      
      plots[[i]] <- ggplot(df, aes(x= V2, y=V1)) +
        geom_point() +
      geom_vline(xintercept = grid[i,2], color="red")+ 
      geom_text(aes(x=grid[i,2], label=grid[i,2], y=3))
    
    }
    
    
    grid.arrange(grobs=plots, nrow=2)


回答1:


Ideally you should use annotate instead. The following code works as expected.

library(ggplot2)
library(grid)
library(gridExtra)


plots <- list()

grid <- data.frame(x=seq(4), y=c(200, 400, 600, 800))

for (i in 1:4) {
  V1 <- rnorm(1000)
  V2 <- seq(1000)
  df <- data.frame(V1, V2)
  
  plots[[i]] <- ggplot(df, aes(x= V2, y=V1)) +
    geom_point() +
    geom_vline(xintercept = grid[i,2], color="red")+ 
    annotate("text", x=grid[i,2], label=grid[i,2], y=3)
  
}


grid.arrange(grobs=plots, nrow=2)

Created on 2020-06-26 by the reprex package (v0.3.0)




回答2:


I'd take a different approach, using facets.

I'd also probably calculate the sample outside the facet/loop (second option)

library(ggplot2)
grid_df<- data.frame(x=1:4, y=c(200, 400, 600, 800))

ggplot(grid_df) +
  geom_vline(aes(xintercept = y), color="red") +
  geom_text(aes(label = y, x = y, y = Inf), vjust = 1) +
  stat_function(
    inherit.aes = FALSE,
    fun = rnorm, 
    n = 600,
    alpha = 0.2,
    geom = "point"
  )+
  facet_wrap(~x, nrow = 2)


## or, if you want always the same sample in each facet: 
set.seed(42)
df_rnorm <- data.frame(V1 = rep(rnorm(1000), 4), V2 = rep(seq(1000), 4), x = rep(1:4, each = 1000))

ggplot(grid_df) +
  geom_vline(aes(xintercept = y), color="red") +
  geom_text(aes(label = y, x = y, y = Inf), vjust = 1) +
  geom_point(data = df_rnorm, aes(V2, V1), alpha = 0.2)+
  facet_wrap(~ x, nrow = 2)

Created on 2020-06-26 by the reprex package (v0.3.0)




回答3:


I had to experiment a little bit to adress the why part of your question. And probably someone else could enrich my explaination with a little bit more expert knowledge and facts (I am just answering based on my gut feeling :D)

As there seems to be no problem, if you print the plots inside the loop or if you print them outside the loop (within another loop that iterates 1:4), I think plot[[i]] only stores the syntax to produce the plots. If you execute plot[[i]] outside of the loop, it uses grid[i,2] to assign label and position of the geom_text part. Outside of the loop i is 4 and thats why all the plots use the same position/label (800).

But I don't really understand why geom_vline does not behave the same way or why aes.inherit or the use of lapply fixes the problem ... If anyone else could shed some light on this, I would appreciate it :)

        library(ggplot2)
        library(grid)
        library(gridExtra)
        
        plots <- list()
        
        grid <- data.frame(x=seq(4), y=c(200, 400, 600, 800))
        
        for (i in 1:4) {
            V1 <- rnorm(1000)
            V2 <- seq(1000)
            df <- data.frame(V1, V2)
            
            plots[[i]] <- ggplot(df, aes(x= V2, y=V1)) +
                geom_point() +
                geom_text(aes(x=grid[i,2], label=grid[i,2], y=3)) +
                geom_vline(xintercept = grid[i,2], color="red") 
                
            
            print(plots[[i]]) # not part of the original syntax
            
        }
        
        
        # leads to wrong position of geom_text
        plots
    
        # leads to wrong position of geom_text
        grid.arrange(grobs=plots, nrow=2)
        
        # correct position of geom_text
        for (i in 1:4){
            print(plots[[i]])
        }
        
        # new grid values also affect plots
        grid <- data.frame(x=seq(4), y=c(2000, 4000, 6000, 8000))
        
        # leads to wrong position of geom_text
        plots
        
        


来源:https://stackoverflow.com/questions/62594080/ggplot2-labeling-graphs-in-a-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!