函数无法找到在该函数的本地环境中定义的公式对象
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)
我正在尝试构建一个可以接受公式列表作为参数的函数。
我首先定义将作为参数输入到函数中的变量。前两个变量是包含布尔信息的命名向量。
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)