为什么R函数不使用父父环境中的变量?

时间:2017-11-01 17:05:19

标签: r

我不知道,为什么glue_data不使用父母环境中提供的变量?见下面的代码。函数test_call_glue_directly返回所需的结果。函数test_call_glue返回错误Error in eval(x, envir = data, enclos = envir) : object 'c_1' not found

当然,我的真实函数有多个变量。 formula_1可能会引用{c_2}{c_3}。或{c_456}{c_7}{c_8}c_*的计数可能会有所不同。

有没有办法专门为调用这个glue_data创建新环境?或者从父环境中提取变量?或者更好的方法来组织我的代码?我不想将参数c_1传递给funciton fill_1,因为在我的真实脚本中,可能存在未知名称的未知变量计数。

fill_1 <- function(letts, n0, formula_x) {
  purrr::cross_df(list(row = n0, column = letts)) %>%
    glue::glue_data(formula_x) %>%
    matrix(ncol = length(letts)) %>%
    as.data.frame
}


test_call_glue <- function() {
  c_1 <- "C"
  formula_1 <-  "={c_1}{row}"
  fill_1(c("A"), c(1:5), formula_1)
}


test_call_glue_directly <- function() {
  # The function without wrapping glue_data in function
  c_1 <- "C"
  formula_1 <-  "={c_1}{row}"
  purrr::cross_df(list(row = c(1:5), column = c("A"))) %>%
    glue::glue_data(formula_1) %>%
    matrix(ncol = 1) %>%
    as.data.frame
}

test_call_glue_directly()
test_call_glue()

3 个答案:

答案 0 :(得分:0)

似乎这个有效。函数fill_1找不到从.GlobalEnv调用的c_1。您的功能是在您的环境.GlobalEnv中创建的,以及他们寻找变量的位置。在这里,我使用c_1.GlobalEnv放回<<-

test_call_glue <- function() {
  c_1 <- "C"
  c_1<<-c_1
  formula_1 <-  "={c_1}{row}"
  ff<-fill_1(letts=c("A"), n0=c(1:5), formula_x=formula_1)
  return(ff)
}

请注意,这个也适用,函数fill_1环境现在是test_call_glue(),因此它可以访问c_1

test_call_glue <- function() {
  fill_1 <- function(letts, n0, formula_x) {
      pp<-purrr::cross_df(list(row = n0, column = letts)) %>%
        glue::glue_data(formula_x) %>%
        matrix(ncol = length(letts)) %>%
        as.data.frame
      return(pp)    
  }
  c_1 <- "C"
  formula_1 <-  "={c_1}{row}"
  ff<-fill_1(letts=c("A"), n0=c(1:5), formula_x=formula_1)
  return(ff)
}

另一种解决方案是从函数的父环境中获取c_1。

fill_1 <- function(letts, n0, formula_x) {
  c_1 <- get ("c_1", parent.frame())
  pp <- purrr::cross_df(list(row = n0, column = letts)) %>%
      glue::glue_data(formula_x) %>%
      matrix(ncol = length(letts)) %>%
      as.data.frame

  return(pp)    
}

这里我创建了一个环境,我存储变量然后检索它。我认为这就是你想要的。

envir_glue<-new.env()

test_call_glue <- function() {
  c_1 <- "C"
  assign("c_1",c_1,envir=envir_glue)
  formula_1 <-  "={c_1}{row}"
  ff<-fill_1(letts=c("A"), n0=c(1:5), formula_x=formula_1)
  return(ff)
}

fill_1 <- function(letts, n0, formula_x) {
  c_1 <- get ("c_1", envir_glue)
  pp <- purrr::cross_df(list(row = n0, column = letts)) %>%
      glue::glue_data(formula_x) %>%
      matrix(ncol = length(letts)) %>%
      as.data.frame

  return(pp)    
}

答案 1 :(得分:0)

感谢塞德里克!我终于明白了什么是错的。

首先,它与胶水无关。与其他功能相同。可选参数.env误导了我。

我的最终解决方案:

fill_3 <- function(x, g) {
  attach(g)
  paste0(x, c_1)
}

test_call_paste <- function() {
  c_1 <- "C"
  c_2 <- "H"
  g_list <- list(c_1=c_1, c_2=c_2)
  ans <- fill_3("4", g_list)
  return(ans)
}

test_call_paste()

这样我可以将fill函数保持为良好的抽象,并在包装​​函数中处理实际的formula字符串和变量。

答案 2 :(得分:0)

我回来重温我的问题。从那时起,我学会了使用点作为我的自定义函数的参数:

fill_3a <- function(x, ...) {
  paste(paste0(x, c_1), paste0(x, c_2), sep=":::")
}
test_call_paste_a <- function() {
  c_1 <- "C"
  c_2 <- "H"
  ans <- fill_3a("4", c_1, c_2)
  return(ans)
}

test_call_paste_a()

将未命名的参数称为我的名字可能没有意义,但它对我的用例有意义,其中第一个参数是用于glue :: glue的字符串(变量按名称替换为它们的值)。 / p>