Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么嵌套的R函数不将现有对象识别为参数?_R_Parameters_Arguments_Parameter Passing_Nested Function - Fatal编程技术网

为什么嵌套的R函数不将现有对象识别为参数?

为什么嵌套的R函数不将现有对象识别为参数?,r,parameters,arguments,parameter-passing,nested-function,R,Parameters,Arguments,Parameter Passing,Nested Function,我正在尝试运行一系列三个嵌套函数。我想将最内部函数的默认参数指定为从最外部函数传递的列表对象中的元素。因为这有点难以解释,所以我创建了一个可复制的示例,它使用了与原始代码相同的参数和对象。请原谅代码的数量,但我想使这个例子尽可能接近原始 函数CreateBirthDates导致该问题。这四个参数都是列表对象sim中的元素(例如,sim$agents$input)。我将sim调用到第一个函数wrapper,然后再次调用第二个函数UpdateAgentStates。在UpdateAgentState

我正在尝试运行一系列三个嵌套函数。我想将最内部函数的默认参数指定为从最外部函数传递的列表对象中的元素。因为这有点难以解释,所以我创建了一个可复制的示例,它使用了与原始代码相同的参数和对象。请原谅代码的数量,但我想使这个例子尽可能接近原始

函数
CreateBirthDates
导致该问题。这四个参数都是列表对象
sim
中的元素(例如,
sim$agents$input
)。我将sim调用到第一个函数
wrapper
,然后再次调用第二个函数
UpdateAgentStates
。在
UpdateAgentStates
中,我想使用
sim
中的其他对象修改
sim$agents$input
(例如,
sim$agents$birth\u day
)。由于这些其他论点总是相同的,我想“硬线”他们。但是如果我运行
包装器
函数,
CreateBirthDates
无法识别
sim
,因此无法指定默认参数

我创建了
CreateBirthDates
的替代版本:
使用sim卡创建生日
。这包括
sim
作为参数。使用包装器函数运行此函数有效

这似乎是一个“这就是R的工作方式”的问题,但我不完全理解为什么。我想提高我的基本编程技能,所以任何建议或意见将不胜感激

多谢各位, 爪哇

见下面的代码:

    # Create some example data and load the package lubridate -----
    library(lubridate)

    t1 <- list("agents"=list("input"=data.frame(id=seq(1:5),class=rep("Male",5),age=rep(6,5))),
        "pars"=list("global"=list("input_age_period"="years",
                                  "birth_day"="01Sep",
                                  "sim_start"=as.POSIXct("2000-10-01"))))

     # Specify the original functions -------

     wrapper <- function(sim,use_sim=FALSE){

       if(use_sim==FALSE){
UpdateAgentStates(agent_states = NULL,sim=sim,init=TRUE)
       } else {
UpdateAgentStates_with_sim(agent_states = NULL,sim=sim,init=TRUE)
       }
     }

     UpdateAgentStates <- function(agent_states = NULL,
     sim = sim,
     init = FALSE
     ) {
       if (init == TRUE) {
input <- sim$agents$input
input <- CreateBirthDate(input)
sim$input <- input
return(sim)
       }
     }

     UpdateAgentStates_with_sim <- function(agent_states = NULL,
                          sim = sim,
                          init = FALSE
     ) {
       if (init == TRUE) {
input <- sim$agents$input
input <- CreateBirthDate_with_sim(input, sim=sim)
sim$input <- input
return(sim)
       }
     }

     CreateBirthDate <- 
     function(input = sim$agents$input, 
     input_age_period = sim$pars$global$input_age_period, 
     birth_day = sim$pars$global$birth_day, 
     starting_day = sim$pars$global$sim_start
     ){

       # Only proceed if there is no birth_date column
       if(is.null(input$birth_date)){
# Loop through each row in the input
for(a in 1:nrow(input)){
  # Is the age_period a year?
  if(input_age_period == "year" || input_age_period == "years") {
    # Determine the first sim_start date after the birth_day
    one_year <- as.period(1, "year")
    s0 <- as.Date(starting_day - (one_year*input$age[a]))
    # Set the format of the birth_day
    birth_day_format <- guess_formats(birth_day,"dm")
    birth_day_format <- paste(birth_day_format,"%Y",sep="")
    # Determine the first birth_day after s0
    s1 <- as.Date(paste(birth_day,year(s0),sep=""), format=birth_day_format)
    if(length(s1)>1){
      s1 <- s1[-(which(is.na(s1)))]
    }
    if(s0 >= s1) {
      input$birth_date[a] <- as.character(s1)
    } else {
      input$birth_date[a] <- as.character(s1-one_year)
    }
  } else {
    # If age period is not a year
    age_period_unit <- as.period(1, input_age_period)
    input$birth_date[a] <- as.character(starting_day - 
                                          (age_period_unit*input$age[a]))
  }
}
       }
       #  Convert birth_date to a POSIXct object
       #  input$birth_date <- as.POSIXct(input$birth_date, tz = 
       #    tz(sim$pars$global$sim_start))  
       return(input)
     }

     # Specify the modified functions -------

     CreateBirthDate_with_sim <- 
       function(input = sim$agents$input, 
       input_age_period = sim$pars$global$input_age_period, 
       birth_day = sim$pars$global$birth_day, 
       starting_day = sim$pars$global$sim_start, sim=sim
       ){

# Only proceed if there is no birth_date column
if(is.null(input$birth_date)){
  # Loop through each row in the input
  for(a in 1:nrow(input)){
    # Is the age_period a year?
    if(input_age_period == "year" || input_age_period == "years") {
      # Determine the first sim_start date after the birth_day
      one_year <- as.period(1, "year")
      s0 <- as.Date(starting_day - (one_year*input$age[a]))
      # Set the format of the birth_day
      birth_day_format <- guess_formats(birth_day,"dm")
      birth_day_format <- paste(birth_day_format,"%Y",sep="")
      # Determine the first birth_day after s0
      s1 <- as.Date(paste(birth_day,year(s0),sep=""), format=birth_day_format)
      if(length(s1)>1){
        s1 <- s1[-(which(is.na(s1)))]
      }
      if(s0 >= s1) {
        input$birth_date[a] <- as.character(s1)
      } else {
        input$birth_date[a] <- as.character(s1-one_year)
      }
    } else {
      # If age period is not a year
      age_period_unit <- as.period(1, input_age_period)
      input$birth_date[a] <- as.character(starting_day - 
                                            (age_period_unit*input$age[a]))
    }
  }
         }
         #  Convert birth_date to a POSIXct object
         #  input$birth_date <- as.POSIXct(input$birth_date, tz = 
         #    tz(sim$pars$global$sim_start))  
         return(input)
       }

     # Try running the wrapper function -------------

     # Original version, doesn't work
     wrapper(t1, use_sim = FALSE)

     # But if I add an argument for sim to CreateBirthDate
     wrapper(t1, use_sim = TRUE)
#创建一些示例数据并加载lubridate包-----
图书馆(lubridate)

t1在另一个全局函数中使用全局函数与在另一个函数中定义函数之间存在差异。在第一个示例中,internal_func的作用域是全局环境,而sim在全局环境中不存在(唯一存在的变量是t1):


t1对于一个最小的、可重复的示例来说,这似乎太多的代码无法排序。
CreateBirthDate
函数默认值似乎都使用了
sim$
,但
sim
不是该函数的参数。我一直不清楚想要的行为是什么。这里的一切都在运行,正如我在R中所期望的那样。R函数中的参数无法看到其自身词法范围之外的变量。如果您希望函数使用值,请将其作为参数传入。感谢您的回复!我想我很困惑,如果
CreateBirthDate
嵌套在
UpdateAgentStates
中,并且
sim
作为参数包含在
UpdateAgentStates
中,为什么
sim
不存在?我认为,作为参数提供给函数的任何内容都将成为工作环境的一部分,并可用于任何后续嵌套函数,如果这有意义的话。。。?再次感谢你的帮助!
t1 <- 1

inner_func <- function() {
  final <- sim*2 
  return(final)
}

outer_func <- function(sim = w){ inner_func() }

outer_func(t1)

Error in inner_func() : object 'sim' not found
t1 <- 1

outer_func <- function(sim = w){ 
  inner_func <- function() {
    final <- sim*2 
    return(final)
  }
  inner_func()
}

outer_func(t1)
[1] 2