0

As I learn R, I am trying to use it in my work. I needed to plot 142 plots and do some stats. Therefore I decided to write the following function:

Melting <- function(df){
  i <- as.character(substitute(df))
  df.m<-melt(df)
  library(grid, lib.loc = "C:/Program Files/R/R-3.6.2/library")
  name_plot = paste(i,".png",sep = "")
  png(name_plot, width = 10, height = 9, units = 'in', res = 700)
  print(ggplot(data = df.m, aes(x=Tissuetype, y=value)) + geom_boxplot(aes(fill=variable)) + stat_compare_means(aes(group = variable), label = "p.signif") + theme(axis.text.x = element_text(angle = 90)))
  dev.off()
}

The function runs fine and takes one of the dataframe present in my environment as an input. For eg: Melting(liver) Having tested that the function successfully plot the graph, I decided to put it in a for loop as I did in bash scripting. However, it throws the following error:

for(i in names){Melting(i)}
 Error in FUN(X[[i]], ...) : object 'variable' not found 

The names vector was created as follows

files = list.files(pattern = "*.csv")
names <-tools::file_path_sans_ext(files)

I have a hunch that the value of I in for loop is getting substituted as string eg: Melting("liver") rather than an argument Melting(liver). But I don't know how to get over it. I read several posts but couldn't understand. Please help

  • 1
    Try `for(i in names){Melting(get(i))}` – Ronak Shah Jun 09 '20 at 08:39
  • Hi, I think that for @Ronak Shah's suggestion to work you still need to read the csv's into the R workspace before you can do `get(i)`. If the `names` objects contains names of files somewhere on disk, I don't think you can directly access them with `get`. – Valeri Voev Jun 09 '20 at 10:21
  • Hi@Ronak. The command did run but didn't produce plots. @Valeri I have a list of data frames. The files have already been read in form of tables using the following command: ```for(i in names){ filepath <- file.path("E:/shantanu_new_tanta/tissue/facet_data/",paste(i,".csv",sep="")) assign(i, read.table(filepath,header = FALSE, col.names = c("Tissuetype", "E", "P"), sep = "\t"))}``` – Rohit Satyam Jun 09 '20 at 12:13
  • if you have a list of df's then instead of `get(i)` can you try `get(df_list[i])` in this case `i` needs to iterate from 1 to `length(df_list)` – Valeri Voev Jun 09 '20 at 12:17
  • Hi @Valerifor. I tried with your suggestion ```for(i in 1:3){Melting(get(l[[i]]))}```. The command did run ```Using Tissuetype as id variables Using Tissuetype as id variables Using Tissuetype as id variables```. However, the plots get overwritten and are saved with name "get" and aren't produced separately. How should I modify this line of code ```i <- as.character(substitute(df))``` to get only value of df(such as liver and not get) to name every new plot – Rohit Satyam Jun 09 '20 at 13:22

1 Answers1

0

All thanks to @Valerifor for helping me out and @Ronak too. The final code is as follows for those who might face same problem

#Reading multiple file list
files = list.files(pattern = "*.csv")


#first making a list of all data frames we wish to have
l <- as.list(tools::file_path_sans_ext(files))

#Loading all files as dataframes together
for(i in l){
  filepath <- file.path("E:/shantanu_new_tanta/tissue/facet_data/",paste(i,".csv",sep=""))
  assign(i, read.table(filepath,header = FALSE, col.names = c("Tissuetype", "E", "P"), sep = "\t"))
}

#Defining a function that plots boxplot with significance values
Melting <- function(df, name_png){
    df.m<-melt(df)
    library(grid, lib.loc = "C:/Program Files/R/R-3.6.2/library")
    name_plot = paste(name_png,".png",sep = "")
    png(name_plot, width = 10, height = 9, units = 'in', res = 700)
    print(ggplot(data = df.m, aes(x=Tissuetype, y=value)) + geom_boxplot(aes(fill=variable)) + stat_compare_means(aes(group = variable), label = "p.signif") + theme(axis.text.x = element_text(angle = 90)))
    dev.off()
}

#Running function on all files in a single go
for(i in 1:3){Melting(get(l[[i]]), l[[i]])}
  • You might be interested in my answer at [How to make a list of data frames]https://stackoverflow.com/questions/17499013/how-do-i-make-a-list-of-data-frames/24376207#24376207). You could avoid the `assign` and `get`s by using a list of data frames. – Gregor Thomas Jun 09 '20 at 14:00
  • E.g., your first `for` loop would be replaced with `data_list <- lapply(files, read.table, header = FALSE, col.names = c("Tissuetype", "E", "P"), sep = "\t")`. – Gregor Thomas Jun 09 '20 at 14:01