我对从父函数中使用不可变变量的优雅方式感兴趣。
让我们看一个例子。
我有包含星期数及其相应值的数据框。
df <- tribble(
~week, ~count,
1, 99.6,
2, 116,
3, 107,
4, 125,
5, 126,
6, 131,
7, 149,
8, 130,
9, 111,
48, 43.4,
49, 136,
50, 133,
51, 115,
52, 93.3
)
以下函数将每周的第一个日期和最后一个日期添加到数据框列中。
add_week_limit_dates <- function(df){
year_change <- ifelse(any(df$week < 25) && any(df$week > 38), TRUE, FALSE)
df %>%
mutate(week_start = week_to_date(week, 1, year_change),
week_end = week_to_date(week, 7, year_change))
}
week_to_date <- function(week, day_of_week, year_change){
paste0(get_year(week, year_change),
"-W", ifelse(week < 10, paste0("0", as.character(week)), week),
"-", day_of_week) %>% ISOweek2date()
}
get_year <- function(week, year_change){
if(isTRUE(year_change)){
ifelse(week < 38, year(Sys.Date()), year(Sys.Date()) - 1)
} else{
year(Sys.Date())
}
}
> add_week_limit_dates(df)
# A tibble: 14 × 4
week count week_start week_end
<dbl> <dbl> <date> <date>
1 1 99.6 2022-01-03 2022-01-09
2 2 116. 2022-01-10 2022-01-16
3 3 107. 2022-01-17 2022-01-23
4 4 125. 2022-01-24 2022-01-30
5 5 126. 2022-01-31 2022-02-06
6 6 131. 2022-02-07 2022-02-13
7 7 149. 2022-02-14 2022-02-20
8 8 130. 2022-02-21 2022-02-27
9 9 111. 2022-02-28 2022-03-06
10 48 43.4 2021-11-29 2021-12-05
11 49 136. 2021-12-06 2021-12-12
12 50 133. 2021-12-13 2021-12-19
13 51 115. 2021-12-20 2021-12-26
14 52 93.3 2021-12-27 2022-01-02
所以,我的问题:是否可以不显式设置公共(public)变量 year_change 并强制子函数在父函数中搜索它?我梦想着下一步
df %>%
mutate(week_start = week_to_date(week, 1),
week_end = week_to_date(week, 7))
UPD - 解决方案
按照建议,我访问了 parent.frame(),但请注意,当您在 dplyr 的方法中使用它时,它不是预期的
add_week_limit_dates <- function(df){
year_change <- ifelse(any(df$week < 25) && any(df$week > 38), TRUE, FALSE)
df$week_start <- week_to_date(df$week, 1)
df$week_end <- week_to_date(df$week, 7)
df
}
week_to_date <- function(week, day_of_week){
paste0(get_year(week, parent.frame()$year_change),
"-W", ifelse(week < 10, paste0("0", as.character(week)), week),
"-", day_of_week) %>% ISOweek2date()
}
...
最佳答案
您可以通过被调用函数的父框架访问调用函数的作用域:
mother <- function(){
year_change = 8
child()
}
child <- function(){
print(parent.frame()$year_change)
}
...或在函数的直接父环境之一中定义它们:
mother <- function(){ ## now the immediate parent environment
year_change = 8
child <- function(){
print(year_change)
}
child()
}
...或在全局环境中:
year_change = 8 ## the global environment
mother <- function(){
print(paste("mom's idea of year_change is:", year_change))
child <- function(){
print(paste("kid's idea of year_change is:", year_change))
}
child()
}
请注意,如果变量具有相同的名称,则直接父环境将优于更远的祖先环境。
范围界定的详细信息,例如在 H. Wickham:Advanced R
编辑
可耻的是忘记了通过利用省略号...
参数来传递变量的可能性。
示例
mother_says <- function(...){
tell_child(...)
}
tell_child <- function(...){
args <- list(...)
print(paste("Mom says:", args$message_to_daughter))
tell_grandchild(...)
}
tell_grandchild <- function(...){
args <- list(...)
print(paste("Granny says:", args$message_to_grandchild))
}
示例的输出:
## > mother_says(message_to_daughter = "Hi, daughter, how're you?",
## + message_to_grandchild = "Grandchild, sweetie!"
## + )
##
## [1] "Mom says: Hi, daughter, how're you?"
## [1] "Granny says: Grandchild, sweetie!"
关于r - 如何从R中的父函数访问变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71972517/