简体   繁体   中英

R Get objects from environment and feed to function

This is probably a pretty trivial question, but I'm much more used to python than to R (the fact I'm mostly a biologist might also play a role...)

What the code below does is plot the counts for each gene in the provided data in an independent panel, and rearrange the legends in order to have a single one for all the panels in the plot.

# function to rearrange plot legend, from here:
# http://rpubs.com/sjackman/grid_arrange_shared_legend. Give credit where credit is due ;)

grid_arrange_shared_legend <- function(...) {
    plots <- list(...)
    g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))$grobs
    legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
    lheight <- sum(legend$height)
    grid.arrange(
        do.call(arrangeGrob, lapply(plots, function(x)
            x + theme(legend.position="none"))),
        legend,
        ncol = 1,
        heights = unit.c(unit(1, "npc") - lheight, lheight))
} 

# make plot for the given gene and assign it to a named object
plot_genes <- function(gene, gID){
    name<-paste0("plotted_counts_for_", gene)
    counts = plotCounts("whatever") # get data using plotCounts from DESeq2 package. the gID is used in here
    return(assign(name, ggplot(counts,
                                # + a bunch of plotting aestetics
                                envir = .GlobalEnv)) #make plot available outside function. Probably I can also use parent.frame()
}                                

# call plot_genes() for each cluster of genes, adjust the legend for multiple plots with  grid_arrange_shared_legend()
plot_cluster_count <- function(cluster,name) { 
    genes = as.vector(as.data.frame(cluster)$Symbol)
    gIDs = as.vector(as.data.frame(cluster)$EMSEMBL)

    pdf(paste0(name,"_counts.pdf"))
    plt = lapply(seq_along(genes), function(x) plot_genes(genes[x], gIDs[x]))
    grid_arrange_shared_legend(plotted_counts_for_gene1, plotted_counts_for_gene2, plotted_counts_for_gene3,plotted_counts_for_gene4)
    dev.off()
}  

# call the whole thing
plot_cluster_count(Cluster_1,"Cluster_1")

This code works. The issue is that it works only when I explicitely hard-code the names of the plots as in grid_arrange_shared_legend(plotted_counts_for_gene1, plotted_counts_for_gene2, plotted_counts_for_gene3,plotted_counts_for_gene4) . However I have plenty of clusters to plot, with different number of genes with different names, so I need to automate the selection of objects to feed to grid_arrange_shared_legend() .

I tried to play around with ls()/objects() , mget() and Google but I can't find a way to get it working, I always end up with Error in plot_clone(plot) : attempt to apply non-function . I traced the error back with options(error=recover) and indeed it comes from grid_arrange_shared_legend() , so to me it looks like I'm not able to feed the objects to the function.

The ultimate goal would be to be able to call plot_cluster_count() within a lapply() statement feeding a list of clusters to iterate through. This should result in one pdf per cluster, each containing one panel per gene.

PS I'm aware that getting the object names from the environment is not the most elegant way to go, it just seemed more straightforward. Any alternative approach is more than welcome

Thanks!

One solution:

# mock data (3 "objects")
set.seed(1)
obj_1 <- list(var = sample(1:100, 1), name = "obj_1")
obj_2 <- list(var = sample(1:100, 1), name = "obj_2")
obj_3 <- list(var = sample(1:100, 1), name = "obj_3")

# any kind of function you want to apply 
f1 <- function(obj, obj_name) {
  print(paste(obj, " -- ", obj_name))
}

# Find all objects in your environment 
list_obj <- ls(pattern = "obj_")

# Apply the previous function on this list
output <- lapply(list_obj, function(x) f1(get(x)$var, get(x)$name))

output
#> [[1]]
#> [1] "27  --  obj_1"
#> 
#> [[2]]
#> [1] "38  --  obj_2"
#> 
#> [[3]]
#> [1] "58  --  obj_3"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM