如何将 R 代码移动到函数中以概括行为
Posted
技术标签:
【中文标题】如何将 R 代码移动到函数中以概括行为【英文标题】:How to move R code into functions to generalise behaviour 【发布时间】:2022-01-23 06:27:10 【问题描述】:我有一大段杂乱无章的 R 代码,其中包含大量难看的重复。有机会大规模减少它。从这段代码开始:
table <-
risk_assigned %>%
group_by(rental_type, room_type) %>%
summarise_all(funs( sum(!is.na(.)) / length(.) ) ) %>%
select(-c(device_id, ts, room, hhi, temp)) %>%
adorn_pct_formatting()
我想将它概括为一个函数,以便它可以重复使用。
LayKable = function(kableDetails)
table <-
risk_assigned %>%
group_by(kableDetails$group1 , kableDetails$group2) %>%
summarise_all(funs( sum(!is.na(.)) / length(.) ) ) #%>%
select(-c(device_id, ts, room, hhi, temp)) %>%
adorn_pct_formatting()
...
kable <- table
return(kable)
kableDetails <- list(
group1 = "rental_type",
group2 = "room_type"
)
newKable <- LayKable(kableDetails)
这种相当半心半意的尝试有助于解释我想要做什么。如何将内容传递给列表中的这个函数(我是 C 程序员,假装它是一个结构)。
【问题讨论】:
如果您总是要使用group1
和group2
列表元素,为什么还要一个参数kableDetails
?为什么不使用LayKable("rental_type", "room_type")
之类的显式参数呢?还有,为什么risk_assigned
是全局变量而不是传入函数?
这是一个最小的例子。我有 6 或 7 个参数要传入。它在列表中更整洁。分配的风险是一个全局变量。
【参考方案1】:
将函数参数传递给函数内的 dplyr
动词时,您必须使用 rlang
术语。但是定义一个函数应该很简单,您可以将许多分组术语传递给:
library(dplyr)
test_func <- function(..., data = mtcars)
# Passing `data` as a default argument as it's nice to be flexible!
data %>%
group_by(!!!enquos(...)) %>%
summarise(across(.fns = sum), .groups = "drop")
test_func(cyl, gear)
#> # A tibble: 8 x 11
#> cyl gear mpg disp hp drat wt qsec vs am carb
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 4 3 21.5 120. 97 3.7 2.46 20.0 1 0 1
#> 2 4 4 215. 821 608 32.9 19.0 157. 8 6 12
#> 3 4 5 56.4 215. 204 8.2 3.65 33.6 1 2 4
#> 4 6 3 39.5 483 215 5.84 6.68 39.7 2 0 2
#> 5 6 4 79 655. 466 15.6 12.4 70.7 2 2 16
#> 6 6 5 19.7 145 175 3.62 2.77 15.5 0 1 6
#> 7 8 3 181. 4291. 2330 37.4 49.2 206. 0 0 37
#> 8 8 5 30.8 652 599 7.76 6.74 29.1 0 2 12
更新 - 添加列表
我认为您的理想是为每个函数调用编写一个参数列表并传递这些参数,而不是在每个调用中写出参数。您可以使用do.call
将命名参数列表传递给函数来执行此操作。同样,当使用dplyr
动词时,您可以在构造列表时使用quote
变量名(这样R 在编译列表时不会尝试在全局环境中找到它们)和!!enquo
每个调用 then在那里使用它们:
library(dplyr)
test_func2 <- function(.summary_var, .group_var, data = mtcars)
data %>%
group_by(!!enquo(.group_var)) %>%
summarise(mean = mean(!!enquo(.summary_var)))
# Test with bare arguments
test_func2(hp, cyl)
#> # A tibble: 3 x 2
#> cyl mean
#> <dbl> <dbl>
#> 1 4 82.6
#> 2 6 122.
#> 3 8 209.
# Construct and pass list
args <- list(.summary_var = quote(hp), .group_var = quote(cyl))
do.call(test_func2, args = args)
#> # A tibble: 3 x 2
#> cyl mean
#> <dbl> <dbl>
#> 1 4 82.6
#> 2 6 122.
#> 3 8 209.
handy guide to tidy evaluation,其中大部分想法都得到了更清楚的解释。
由reprex package (v2.0.1) 于 2021 年 12 月 21 日创建
【讨论】:
以上是关于如何将 R 代码移动到函数中以概括行为的主要内容,如果未能解决你的问题,请参考以下文章
如何将此 javascript 和 HTML 代码添加到 Angular 项目中?我可以从 javascript 函数中以角度呈现 html 吗?