gpt4 book ai didi

r - 如何在 dplyr::across() 中使用返回多个值的函数?

转载 作者:行者123 更新时间:2023-12-04 12:30:10 25 4
gpt4 key购买 nike

我想在多个列上执行多个操作,我可以使用 dplyr::across() 这样做:

library(tidyverse)

df = tibble(x=1:5, p1=x*2, p2=x*4, p3=x*5)
r1 = df %>%
mutate(across(starts_with("p"), c(inf=~.x-1, sup=~.x+1)))
r1
#> # A tibble: 5 x 10
#> x p1 p2 p3 p1_inf p1_sup p2_inf p2_sup p3_inf p3_sup
#> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 2 4 5 1 3 3 5 4 6
#> 2 2 4 8 10 3 5 7 9 9 11
#> 3 3 6 12 15 5 7 11 13 14 16
#> 4 4 8 16 20 7 9 15 17 19 21
#> 5 5 10 20 25 9 11 19 21 24 26
names(r1)
#> [1] "x" "p1" "p2" "p3" "p1_inf" "p1_sup" "p2_inf" "p2_sup"
#> [9] "p3_inf" "p3_sup"

但是,如果函数计算很多东西,这不是很好的可扩展性,因为它会被评估两次。

相反,如果我可以使用一个函数来计算需要计算的东西,然后返回 2 个(或更多)结果的列表,那就太好了。

例如,考虑这个例子:

#perform heavy calculation on x2 and return 2 flavours of it
f = function(x) {
x2=x #wow, such heavy, very calculate
Sys.sleep(1)
data.frame(inf=x2-10, sup=x2+10)
}

r2 = df %>%
mutate(across(starts_with("p"), f, .names="{.col}_{.fn}"))
r2
#> # A tibble: 5 x 7
#> x p1 p2 p3 p1_1$inf $sup p2_1$inf $sup p3_1$inf $sup
#> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 2 4 5 -8 12 -6 14 -5 15
#> 2 2 4 8 10 -6 14 -2 18 0 20
#> 3 3 6 12 15 -4 16 2 22 5 25
#> 4 4 8 16 20 -2 18 6 26 10 30
#> 5 5 10 20 25 0 20 10 30 15 35
names(r2)
#> [1] "x" "p1" "p2" "p3" "p1_1" "p2_1" "p3_1"
map_chr(r2, class)
#> x p1 p2 p3 p1_1 p2_1
#> "integer" "numeric" "numeric" "numeric" "data.frame" "data.frame"
#> p3_1
#> "data.frame"

reprex package 创建于 2021-10-25 (v2.0.1)

使用 rbind() 而不是 data.frame() 会得到相同的结果,但名称略有不同(p1_1$inf 变为p1_1[​​,"inf"]) 和一个不同的类(data.frame 变为 c("matrix", "array")

此外,当使用单个函数时,{.fn}是函数的位置,因此存在命名问题。

我也尝试过 unnest() 结果,但没有成功。

有没有办法使用 across() 中的函数获得我的第一个输出的准确结果?

最佳答案

也许这对你有帮助?

library(tidyverse)

f = function(x, y) {
x2=x
tibble(!!paste0(y, '_inf') := x2-10,
!!paste0(y, '_sup') := x2+10)
}

imap_dfc(select(df, starts_with('p')), f)

# p1_inf p1_sup p2_inf p2_sup p3_inf p3_sup
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 -8 12 -6 14 -5 15
#2 -6 14 -2 18 0 20
#3 -4 16 2 22 5 25
#4 -2 18 6 26 10 30
#5 0 20 10 30 15 35

绑定(bind)到原始df

bind_cols(df %>% select(-starts_with('p')), 
imap_dfc(select(df, starts_with('p')), f))

关于r - 如何在 dplyr::across() 中使用返回多个值的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69705697/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com