私は実行しようとしている一連の3つのネストされた関数を持っています。私は最も内側の関数のデフォルトの引数を、最も外側の関数から渡されるリストオブジェクト内の要素として指定したいと思います。これは説明するのが少し難しいので、元のコードと同じ引数とオブジェクトを使用する再現可能な例を作成しました。コードの量を許してくださいが、私はこの例をできるだけオリジナルに近づけたいと思っていました。ネストしたR関数が既存のオブジェクトを引数として認識しないのはなぜですか?
機能CreateBirthDates
が問題の原因です。 4つの引数は、リストオブジェクト内のすべての要素であるsim
(たとえば、sim$agents$input
)です。私はsimに最初の関数wrapper
を呼び出し、次に2番目の関数UpdateAgentStates
を呼び出します。 UpdateAgentStates
の中でsim
(例えば、sim$agents$birth_day
)内の他のオブジェクトを使用してsim$agents$input
を変更したいと思います。これらの他の引数は常に同じなので、私はそれらを「ハードワイヤリング」したいと思います。しかし、wrapper
関数を実行すると、CreateBirthDates
はsim
を認識せず、したがってデフォルトの引数を指定することはできません。
CreateBirthDates
の代替バージョン: CreateBirthDates_with_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)
これは、最小限で再現性のある例を並べ替えるにはあまりにも多くのコードと同じように思えます。 'CreateBirthDate'関数のデフォルト値はすべて' sim $ 'を使うようですが' sim'はその関数のパラメータではありません。希望の振る舞いが何であるかは私には不明です。 R関数のパラメータは、それ自身のレキシカルスコープの外の変数を見ることができません。関数が値を使用するようにするには、その値をパラメータとして渡します。 – MrFlick