[英]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...) 这可能是一个相当琐碎的问题,但是我比R更加习惯于python(事实上我主要是生物学家也可能起着作用……)
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)
. 问题是,仅当我像grid_arrange_shared_legend(plotted_counts_for_gene1, plotted_counts_for_gene2, plotted_counts_for_gene3,plotted_counts_for_gene4)
那样明确地对图的名称进行硬编码时,它才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()
. 但是,我要绘制很多簇,具有不同名称的不同数量的基因,因此我需要自动选择要馈送到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
. 我试图与ls()/objects()
, mget()
和Google一起玩,但是我找不到一种使它正常工作的方法,我总是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. 我使用options(error=recover)
追溯了错误,并且确实来自grid_arrange_shared_legend()
,所以对我来说似乎无法将对象提供给函数。
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. 最终目标是能够在lapply()
语句中调用plot_cluster_count()
,从而提供要迭代的集群列表。 This should result in one pdf per cluster, each containing one panel per gene. 这将导致每个簇一个pdf,每个基因每个包含一个面板。
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. PS我知道从环境中获取对象名称并不是最优雅的方法,它看起来更加简单。 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"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.