【问题标题】:Calculate mean-deviated values (subtract mean of all columns except one from this one column)计算平均偏差值(从这一列中减去除一列之外的所有列的平均值)
【发布时间】:2021-11-30 01:17:13
【问题描述】:

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

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')"

【问题讨论】:

    标签: purrr


    【解决方案1】:

    我们可以使用map_dfctransmute 来创建*_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_varc_bard_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 package (v2.0.1) 于 2021 年 12 月 20 日创建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-20
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-03
      相关资源
      最近更新 更多