【问题标题】:Function not able to find a formula object that was defined in the local environment of that function函数无法找到在该函数的本地环境中定义的公式对象
【发布时间】:2019-08-21 22:11:51
【问题描述】:

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

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

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

第三个参数是公式对象的列表。公式是一个“语言”类对象,除非使用 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

最后,是时候使用逻辑论证了!这里的目标是让函数使用逻辑参数中提供的方程式,通过使用前一行中可用的值来“更新”矩阵的下一行。

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

  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 

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

附:我确信使用类似的参数格式编写此函数可能会有更好/更优雅的方式,我很想知道它们。但是出于学习的目的,我真的很想知道我写这个函数的方法是否可行。

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

【问题讨论】:

    标签: r boolean-logic boolean-algebra


    【解决方案1】:

    参数列表解决方案

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

    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)
    

    【讨论】:

    • 非常感谢丹尼尔!您能否解释一下为什么我的代码一开始就不起作用?为什么 f_eval 没有在我的自定义函数的本地环境中评估公式?
    • 似乎环境if评估附加到logic中的函数。它们要么是首先在 global 中创建的,并且坚持它,要么 global 只是默认设置。起初,我认为 eval 函数需要一个 env 来评估,但在这种情况下,您的解决方案应该可以正常工作,因为合理的默认值是 parent.frame()。长话短说,函数是在全局范围内评估的,所以它在函数之外工作,但不在函数内部。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    相关资源
    最近更新 更多