计算平均偏差值(从这一列中减去除一列以外的所有列的平均值)

问题描述 投票:0回答:1

我有一个具有以下结构的数据集:

df <- data.frame(id = 1:5,
                 study = c("st1","st2","st3","st4","st5"),
                 a_var = c(10,20,30,40,50),
                 b_var = c(6,5,4,3,2),
                 c_var = c(3,4,5,6,7),
                 d_var = c(80,70,60,50,40))

我想计算名称中包含 _var 的每一列与名称中包含 _var 的所有其他列的平均值之间的差异,如下所示:

mean_deviated_value <- function(data, variable) {
  md_value = data[,variable] - rowMeans(data[,names(data) != variable])
  md_value
  }
    
df$a_var_md <- mean_deviated_value(dplyr::select(df, contains("_var")), "a_var")
df$b_var_md <- mean_deviated_value(dplyr::select(df, contains("_var")), "b_var")
df$c_var_md <- mean_deviated_value(dplyr::select(df, contains("_var")), "c_var")
df$d_var_md <- mean_deviated_value(dplyr::select(df, contains("_var")), "d_var")

这给了我想要的输出:

  id study a_var b_var c_var d_var   a_var_md  b_var_md c_var_md d_var_md
1  1   st1    10     6     3    80 -19.666667 -12.33333    -9.80 83.80000
2  2   st2    20     5     4    70  -6.333333 -16.91667   -10.35 70.76667
3  3   st3    30     4     5    60   7.000000 -21.50000   -10.90 57.73333
4  4   st4    40     3     6    50  20.333333 -26.08333   -11.45 44.70000
5  5   st5    50     2     7    40  33.666667 -30.66667   -12.00 31.66667

如何一次完成,而不重复代码,最好使用

dplyr
/
purrr

我试过这个:

df %>%
  mutate(across(contains("_var"), ~ list(md = .x - rowMeans(select(., contains("_var") & !.x)))))

得到这个错误:

Error: Problem with `mutate()` input `..1`.
ℹ `..1 = across(...)`.
x no applicable method for 'select' applied to an object of class "c('double', 'numeric')"
r purrr
1个回答
1
投票

我们可以使用

map_dfc
transmute
创建 *_md 列,以及 glue syntax 的名称。

library(tidyverse)

nms <- names(df) %>%
        str_subset('^.*_')

bind_cols(df, map_dfc(nms, ~transmute(df, '{.x}_md' := mean_deviated_value(select(df, contains("_var")), .x))))
#>   id study a_var b_var c_var d_var   a_var_md  b_var_md  c_var_md d_var_md
#> 1  1   st1    10     6     3    80 -19.666667 -25.00000 -29.00000 73.66667
#> 2  2   st2    20     5     4    70  -6.333333 -26.33333 -27.66667 60.33333
#> 3  3   st3    30     4     5    60   7.000000 -27.66667 -26.33333 47.00000
#> 4  4   st4    40     3     6    50  20.333333 -29.00000 -25.00000 33.66667
#> 5  5   st5    50     2     7    40  33.666667 -30.33333 -23.66667 20.33333

注意如果你使用赋值。第一次

rowMeans
将与
b_var
c_bar
d_bar
一起计算。但是第二次,
contains("_var")
还将捕获之前创建的
a_var_md
并使用它来计算均值。我不知道这是否是有意为之的行为,但值得一提。

df$a_var_md <- mean_deviated_value(dplyr::select(df, contains("_var")), "a_var")
select(df, contains("_var"))
#>   a_var b_var c_var d_var   a_var_md
#> 1    10     6     3    80 -19.666667
#> 2    20     5     4    70  -6.333333
#> 3    30     4     5    60   7.000000
#> 4    40     3     6    50  20.333333
#> 5    50     2     7    40  33.666667

我们可以通过将

contains("_var")
替换为
matches("^.*_var$")

来避免这种情况

reprex 包 (v2.0.1) 于 2021-12-20 创建

© www.soinside.com 2019 - 2024. All rights reserved.