访问函数中的多个匹配对象,而无需在函数调用中明确声明名称

时间:2015-11-12 16:06:00

标签: r function ggplot2 environment scoping

我想开发一个简单的函数,使我能够保存特定特征的图形。例如,我正在运行一些分析,产生一组直方图:

# Data  and Libs
data(mtcars); require(ggplot2)

# Graphs

## A
grph_a <- ggplot(data = mtcars) +
  geom_histogram(aes(mpg)) +
  ggtitle("MPG")

## B
grph_b <- ggplot(data = mtcars) +
  geom_histogram(aes(cyl)) +
  ggtitle("CYL")

不是为每个图形编写ggsave命令,而是希望通过函数来​​完成。这是有道理的,因为我将在各种类似项目中为许多图表重复相同的步骤。我希望函数做一件事:

  • 对于名称中包含特定字符串的所有图表,使用设置参数运行ggsave并保存它们以提供路径。

理想情况下,我希望函数调用看起来像那样

ExportGraphs(graphNamePhrase = "grph_", filesPath = "Somewhere/GaphsAndStuff/)

我不想指定更多东西。

功能

我的功能如下:

ExportGraphs <- function(graphNamePhrase = "grph_",
                         filesPath, objects = ls()) {

  # Check if required packages are available
  req_pkgs <- c("ggplot2","grid")
  ## Check if the package is loaded and load if needed
  for (i in 1:length(req_pkgs)) {
    pkg <- req_pkgs[i]
    if (length(grep(pkg, search())) == 0) {
      lapply(pkg, require, character.only = TRUE)
    }
  }

  # Create list of objects
  save_grphs <- grep(pattern = graphNamePhrase, x = objects,
                     ignore.case = TRUE, value = TRUE)

  # Create save loop
  for (i in 1:length(save_grphs)) {

    # Create file path
    fle_path <- paste0(filesPath, save_grphs[i], ".png")

    # Save file
    ggsave(filename = fle_path, plot = save_grphs[i],
           width = 7, height = 7, units = 'cm', scale = 2, dpi = 600)
  }

}

问题

显然,代码:

  save_grphs <- grep(pattern = graphNamePhrase, x = objects,
                     ignore.case = TRUE, value = TRUE)

不会工作,因为通过objects = ls()传递的内容将是一个字符串。我的问题是如何解决它。有没有办法在调用函数的父框架上使用get?不是最简单的解决方案,但我可以通过字符串搜索对象。或者我可以在函数调用中使用ls运行grep并传递所有匹配的对象吗?

评论后续行动

MGET

我使用mget尝试了解决方案:

ExportGraphs <- function(graphNamePhrase = "grph_",
                         filesPath, objects = ls()) {

  # Check if required packages are available
  req_pkgs <- c("ggplot2","grid")
  ## Check if the package is loaded and load if needed
  for (i in 1:length(req_pkgs)) {
    pkg <- req_pkgs[i]
    if (length(grep(pkg, search())) == 0) {
      lapply(pkg, require, character.only = TRUE)
    }
  }

  # Create list of objects
  save_grphs <- grep(pattern = graphNamePhrase, x = objects,
                     ignore.case = TRUE, value = TRUE)
  save_grphs <- mget(objects[save_grphs])

  # Create save loop
  for (i in 1:length(save_grphs)) {

    # Create file path
    fle_path <- paste0(filesPath, save_grphs[i], ".png")

    # Save file
    ggsave(filename = fle_path, plot = save_grphs[[i]],
           width = 7, height = 7, units = 'cm', scale = 2, dpi = 600)
  }

}

但似乎我必须调整循环,因为订阅似乎超出范围:

Error in save_grphs[[i]] : subscript out of bounds
Called from: inherits(plot, "ggplot")

2 个答案:

答案 0 :(得分:2)

这对我有用。有许多地方可以进一步优化功能:

ExportGraphs <- function(graphNamePhrase = "grph_",
                         filesPath, objects = ls()) {

  # Check if required packages are available
  req_pkgs <- c("ggplot2","grid")
  ## Check if the package is loaded and load if needed
  for (i in 1:length(req_pkgs)) {
    pkg <- req_pkgs[i]
    if (length(grep(pkg, search())) == 0) {
      lapply(pkg, require, character.only = TRUE)
    }
  }

  # Create list of objects
  index <- grep(pattern = graphNamePhrase, x = objects,
                     ignore.case = TRUE)
  save_grphs <- mget(objects[index])
  # Create save loop
  for (i in 1:length(save_grphs)) {

    # Create file path
    fle_path <- paste0(filesPath, objects[index][i], ".png")

    # Save file
    ggsave(filename = fle_path, plot = save_grphs[[i]],
           width = 7, height = 7, units = 'cm', scale = 2, dpi = 600)
  }

}

答案 1 :(得分:1)

尝试这样的事情:

ExportGraphs <- function(graphNamePhrase = "grph_", 
                         filesPath = "Somewhere/GaphsAndStuff",
                         object = ls()) {
  lapply(object[substr(names(object), 1, nchar(graphNamePhrase)) == graphNamePhrase], 
         function(plot.list.el){
           ggsave(plot.list.el, filename = paste(filesPath, paste0(names(plot.list.el), 
                                                                   ".pdf"),
                                                 sep = "/"))
         })
}


# testing the function
dat <- data.frame(x = rnorm(100))
object <- list(grph_asd = ggplot(dat, aes(x = x)) + geom_histogram(),
               grp_noplot = ggplot(dat, aes(x)) + geom_histogram())

# save the first, but not the second plot to the working directory

ExportGraphs(filesPath = "~", object = object)