函数无法找到在该函数的本地环境中定义的公式对象

Function not able to find a formula object that was defined in the local environment of that function

我正在尝试构建一个可以接受公式列表作为参数的函数。

我首先定义将作为参数输入到函数中的变量。前两个变量是包含布尔信息的命名向量。

named_variable_vector <- c(0, 1, 1)
names(named_variable_vector) <- c("M", "E", "L")
named_variable_vector

named_parameter_vector <- c(0, 0)
names(named_parameter_vector) <- c("G_e", "L_e")
named_parameter_vector

第三个参数是公式对象列表。公式是一个 "language" class 对象,在明确告知使用 f_eval() 函数之前不会对其求值。

logic_list <- list(~((G_e + 1)*(L + L_e + L*L_e))%%2, ~M , ~((G_e + 1)*E*L_e)%%2)

好的,是时候构建函数了。第一步是在函数内创建局部变量。这些局部变量将以 named_vector 个参数的名称命名。

Boolean_state_space <- function(variables, parameters, logic) {

  variable_names <- names(variables)
  parameter_names <- names(parameters)

  ####generate local variables

  #assign variable values to variable names
  for (i in 1:length(variables)) {
    assign(variable_names[i], variables[i])

  }
  #assign parameter values to parameter names
  for (j in 1:length(parameters)) {
    assign(parameter_names[j], parameters[j])
  }

然后我初始化一个矩阵。之后,我打印出局部变量来测试它们是否成功制作。这只是一条测试线,不会出现在函数的最终版本中。

#initialize matrix
  state_space_matrix <- matrix(nrow = 4, ncol = length(c(variable_names, parameter_names)))
  colnames(state_space_matrix) <- c(variable_names, parameter_names)
  rownames(state_space_matrix) <- c(1:nrow(state_space_matrix))
  row.names(state_space_matrix)[1] <- c("t")


  state_space_matrix[1,] <- c(variables, parameters)
  state_space_matrix[,c(ncol(state_space_matrix) - 1, ncol(state_space_matrix) )] <-parameters
  print(state_space_matrix) #test to see if matrix was initialized succesfully
  print(c(M, E, L, G_e, L_e)) #test to see if local variables were successfully defined within the function

最后,是时候使用逻辑参数了!这里的目标是让函数使用逻辑参数中提供的等式 "update" 矩阵的下一行,方法是使用上一行中可用的值。

第一行按顺序计算方程,然后将这些值分配给矩阵中的下一行。 这是错误发生的地方。

  for (k in 2:nrow(state_space_matrix)) {

    for (h in 1:length(variable_names)) {
      state_space_matrix[k, variable_names[h]] <- f_eval(logic[[h]])
      print("test")

    }

第二行现在使用矩阵中最近更新的行中的值重新分配变量的值。

for (g in 1:length(variable_names)) {
      assign(variable_names[g], state_space_matrix[k, g])
    } 
  }
  print(state_space_matrix)  
}  #end of function

好的,当我 运行 带有我在开始时设置的参数的函数时:

Boolean_state_space(named_variable_vector, named_parameter_vector, logic_list)

我收到以下错误:

Error in eval(expr, data, expr_env) : object 'G_e' not found 

我这辈子都想不通为什么。 为什么函数看不到我之前在其中定义的局部变量?需要使用这些变量来计算公式。

P.S。我确信可能有一种 better/more 优雅的方式来使用类似的参数格式编写此函数,我很想知道它们。但是为了学习,我很想知道我写这个函数的方法能不能行得通。

P.P.S。当我单独 运行 函数的内部(在全局环境中也称为)时,我的方法效果很好。结果如下所示:

带参数列表的解决方案

我通过使用参数列表而不是依赖正确的环境来明确数据来解决这个问题。

Boolean_state_space <- function(variables, parameters, logic) {

    variable_names <- names(variables)
    parameter_names <- names(parameters)

####generate local variables

                                        #assign variable values to variable names
    for (i in 1:length(variables)) {
        assign(variable_names[i], variables[i])

    }
    print(variable_names)
                                        #assign parameter values to parameter names
    for (j in 1:length(parameters)) {
        assign(parameter_names[j], parameters[j])
    }


                             #initialize matrix
    state_space_matrix <- matrix(nrow = 4, ncol = length(c(variable_names, parameter_names)))
    colnames(state_space_matrix) <- c(variable_names, parameter_names)
    rownames(state_space_matrix) <- c(1:nrow(state_space_matrix))
    row.names(state_space_matrix)[1] <- c("t")


    state_space_matrix[1,] <- c(variables, parameters)
    state_space_matrix[,c(ncol(state_space_matrix) - 1, ncol(state_space_matrix) )] <-parameters
    print(state_space_matrix) #test to see if matrix was initialized succesfully
    print(c(M, E, L, G_e, L_e)) #test to see if local variables were successfully defined within the function

## CREATE PARAMETER LIST

    param_list <- split(unname(parameters), names(parameters))
    param_list <- c(split(unname(variables), names(variables)), param_list)
    cols <- names(variables)
    for (k in 2:nrow(state_space_matrix)) {

        for (h in 1:length(variable_names)) {
            state_space_matrix[k, cols[h]] <- lazyeval::f_eval(logic[[h]], param_list)
            print("test")

        }
## UPDATE PARAMETER LIST WITH CURRENT VALUES 
        for (g in 1:length(variable_names)) {
            param_list[variable_names[g]] <- state_space_matrix[k, g]
        }
    }
    print(state_space_matrix)
}

Boolean_state_space(named_variable_vector, named_parameter_vector, logic_list)

使用环境的替代解决方案

Boolean_state_space <- function(variables, parameters, logic) {

    variable_names <- names(variables)
    parameter_names <- names(parameters)

####generate local variables

                                        #assign variable values to variable names
    for (i in 1:length(variables)) {
        assign(variable_names[i], variables[i])

    }
                                        #assign parameter values to parameter names
    for (j in 1:length(parameters)) {
        assign(parameter_names[j], parameters[j])
    }

    state_space_matrix <- matrix(nrow = 4, ncol = length(c(variable_names, parameter_names)))
    colnames(state_space_matrix) <- c(variable_names, parameter_names)
    rownames(state_space_matrix) <- c(1:nrow(state_space_matrix))
    row.names(state_space_matrix)[1] <- c("t")


    state_space_matrix[1,] <- c(variables, parameters)
    state_space_matrix[,c(ncol(state_space_matrix) - 1, ncol(state_space_matrix) )] <-parameters
    print(state_space_matrix) #test to see if matrix was initialized succesfully
    print(c(M, E, L, G_e, L_e)) #test to see if local variables were successfully defined within the function
    print(parent.frame())
# Get correct environment
    env <- pryr::where(variable_names[1])
    for (k in 2:nrow(state_space_matrix)) {

        for (h in 1:length(variable_names)) {
# Set environment to evaluate functions in 
            rlang::f_env(logic[[h]]) <- env
            state_space_matrix[k, variable_names[h]] <- lazyeval::f_eval(logic[[h]])
            print("test")

        }

        for (g in 1:length(variable_names)) {
            assign(variable_names[g], state_space_matrix[k, g])
        } 
    }
    print(state_space_matrix)  
}

Boolean_state_space(named_variable_vector, named_parameter_vector, logic_list)