Search code examples
rloopsggplot2histogram

stat_function conflict with loop in R


I have a table called join_boin. and there is 4 column.

list <- c("a", "b", "c", "d)

function <- function(a){
  
  for (i in list){
    table %>%
      ggplot(aes(!!as.name(i)))+
      geom_histogram(aes(y=amount)) +
  stat_function(fun = dnorm, args = list(mean = mean(table$a), sd = sd(table$a)))  -> result
    
    print(result)
  }
}

When I use a loop to create a distribution for 4 variable's histograms, I don't know how to deal with (mean = mean(table $ DIFFERENT VARIABLES) ...


Solution

  • Instead of $, use [[. In the OP's code, the argument passed into function is av_total, whereas the for loop uses the list object created outside the function. It should be the same as av_total (or change the argument to 'av_total_list')

    functiona <- function(data, av_total_list){  
       for(av_total in av_total_list) {
        data %>%
          ggplot(aes(!!as.name(av_total)))+
          geom_histogram(aes(y= ..density..), bins = 42) +
      stat_function(fun = dnorm, colour = "red", 
                    args = list(mean = mean(data[[av_total]]),
                 sd = sd(data[[av_total]])))  -> myresult
        
        print(myresult)
      }
    }
    

    and call it as

    functiona(join_boston, list)
    

    reproducible with

    vec <- c('mpg', 'disp', 'hp')
    functiona(mtcars, vec)
    

    The above function just print the output into the console. Instead, it may be better to create a function that return the output and loop over the list and apply the function

    library(dplyr)
    library(ggplot2)
    library(purrr)
    functionb <- function(data, av_total) {
          data %>%
            ggplot(aes(.data[[av_total]])) + 
                geom_histogram(aes(y = ..density..), bins = 42) + 
                stat_function(fun = dnorm, colour = "red",
                  args = list(mean = mean(data[[av_total]], na.rm = TRUE),
                            sd = sd(data[[av_total]], na.rm = TRUE)))
           }
    

    and call the function by loop over the column names

    out <- map(list, ~ functionb(join_boston, .x))
    

    As a reproducible example for testing

    data(mtcars)
    library(ggpubr)
    vec <- c('mpg', 'disp', 'hp')
    out <- map(vec, ~ functionb(mtcars, .x))
    ggarrange(plotlist = out, ncol = 2, nrow = 2)
    

    -output

    enter image description here