【问题标题】:how to make an average with SD across all combination如何在所有组合中使用 SD 求平均值
【发布时间】:2021-07-15 22:31:17
【问题描述】:

我有这样的数据

    df<- structure(list(data = c("A", "AA", "AAA", "AB", "ABN", "AHG", 
"ANBV"), G1_1 = c(1677.1, 956, 57.7, 44.5, 1578.2, 1184.8, 1958.5
), G1_2 = c(1296.9, 1230.2, 68.4, 57.5, 925.1, 1275.7, 2143.6
), G2_1 = c(7012.5, 2087.9, 146.7, 80, 6278.5, 3076.9, 808), 
    G2_2 = c(13470.8, 3926.6, 226.5, 212.6, 12569.4, 6569, 2479.8
    ), Vok3_1 = c(911, 832.8, 50.8, 34.8, 916.6, 1358.5, 1540.4
    ), Vok3_2 = c(5121.9, 1029.6, 108.9, 135, 3624.5, 1971.3, 
    1851.4), Vok4_1 = c(5136.7, 892.1, 78, 60.4, 3106.6, 1578.6, 
    1132.1), Vok4_2 = c(6313.4, 1180.8, 112, 163.4, 4639.8, 2506.4, 
    879.1)), class = "data.frame", row.names = c(NA, -7L))

我想做的是得到标准差和中位数,我不成功

这是我尝试和想要得到的东西

df_med <- as.data.frame(df %>% group_by(data = substr(data, 1, 2,3,4)) %>% summarise_all(funs(median)))

我想要的方法是获取每行每两列之间的中位数或 sd,例如前两列 G1_1 和 G1_2 以及 G2_1 和 G2_2 之间等

我要找的输出是这样的

data    G1        G2         Vok3          Vok4
A       1487    10241.65    3016.45   5725.05
AA     1093.1   3007.25    931.2      1036.45
AAA    63.05    186.6      79.85       95
AB      51      146.3       84.9       111.9
ABN    1251.65  9423.95     2270.55   3873.2
AHG   1230.25   4822.95.    1664.9    2042.5
ANBV    2051.05 1643.9      1695.9    1005.6

【问题讨论】:

    标签: r dplyr tidyr


    【解决方案1】:

    summarise进行分组之前,我们可能需要重塑为“长”(pivot_longer

    1. 将除第一个“数据”列之外的列重新整形为“长”,捕获names_pattern_之前的列名中的子字符串
    2. 按“数据”分组,summarise across 所有其他列得到median
    library(dplyr)
    library(tidyr)
    df_median <- df %>% 
        pivot_longer(cols = -data, names_to = ".value",
            names_pattern = "(.*)_\\d+") %>% 
        group_by(data) %>%
        dplyr::summarise(across(everything(), median, na.rm = TRUE))
    

    -输出

    df_median
    # A tibble: 7 x 5
      data      G1     G2   Vok3  Vok4
      <chr>  <dbl>  <dbl>  <dbl> <dbl>
    1 A     1487   10242. 3016.  5725.
    2 AA    1093.   3007.  931.  1036.
    3 AAA     63.0   187.   79.8   95 
    4 AB      51     146.   84.9  112.
    5 ABN   1252.   9424. 2271.  3873.
    6 AHG   1230.   4823. 1665.  2042.
    7 ANBV  2051.   1644. 1696.  1006.
    

    从宽格式,我们可以再次转换为'long' as

    df_median %>% 
       pivot_longer(cols = -data, names_to = 'key') %>% 
       arrange(data)
    # A tibble: 28 x 3
       data  key     value
       <chr> <chr>   <dbl>
     1 A     G1     1487  
     2 A     G2    10242. 
     3 A     Vok3   3016. 
     4 A     Vok4   5725. 
     5 AA    G1     1093. 
     6 AA    G2     3007. 
     7 AA    Vok3    931. 
     8 AA    Vok4   1036. 
     9 AAA   G1       63.0
    10 AAA   G2      187. 
    # … with 18 more rows
    

    或者不是在两个单独的步骤中执行此操作,而是对所有列进行整形,然后获取“键”列的子字符串并用于分组以获取“值”的median

    library(stringr)
    df %>% 
       pivot_longer(cols = -data, names_to = "key") %>%
       group_by(data, key = str_remove(key, "_\\d+")) %>% 
       summarise(value = median(value), .groups = 'drop')
    # A tibble: 28 x 3
       data  key     value
       <chr> <chr>   <dbl>
     1 A     G1     1487  
     2 A     G2    10242. 
     3 A     Vok3   3016. 
     4 A     Vok4   5725. 
     5 AA    G1     1093. 
     6 AA    G2     3007. 
     7 AA    Vok3    931. 
     8 AA    Vok4   1036. 
     9 AAA   G1       63.0
    10 AAA   G2      187. 
    # … with 18 more rows
    

    如果dplyr 版本旧,则使用summarise_all

    df %>% 
        pivot_longer(cols = -data, names_to = ".value",
            names_pattern = "(.*)_\\d+") %>% 
        group_by(data) %>%
        dplyr::summarise_all(median, na.rm = TRUE)
    # A tibble: 7 x 5
      data      G1     G2   Vok3  Vok4
      <chr>  <dbl>  <dbl>  <dbl> <dbl>
    1 A     1487   10242. 3016.  5725.
    2 AA    1093.   3007.  931.  1036.
    3 AAA     63.0   187.   79.8   95 
    4 AB      51     146.   84.9  112.
    5 ABN   1252.   9424. 2271.  3873.
    6 AHG   1230.   4823. 1665.  2042.
    7 ANBV  2051.   1644. 1696.  1006.
    

    或者使用split.defaultbase R变成一个list的data.frames,使用rowMediansmatrixStats转换成matrix

    library(matrixStats)
    cbind(df[1], sapply(split.default(df[-1], sub("_\\d+$", "", names(df)[-1])), 
           function(x) rowMedians(as.matrix(x))))
    data      G1       G2    Vok3    Vok4
    1    A 1487.00 10241.65 3016.45 5725.05
    2   AA 1093.10  3007.25  931.20 1036.45
    3  AAA   63.05   186.60   79.85   95.00
    4   AB   51.00   146.30   84.90  111.90
    5  ABN 1251.65  9423.95 2270.55 3873.20
    6  AHG 1230.25  4822.95 1664.90 2042.50
    7 ANBV 2051.05  1643.90 1695.90 1005.60
    

    【讨论】:

    • 我收到此错误Error: across()` 只能在 dplyr 动词中使用。运行 rlang::last_error() 以查看错误发生的位置。`
    • @Learner 尝试添加dplyr::summarise 我假设您的dplyr 版本>= 1.0.0
    • 有没有办法让它变长? `gather(df_median, key, value, -c(data)) %>%arrange(data)' 我已经接受了你的回答,但如果你能帮我把它弄长,我会很高兴我使用 df_median 作为输出你的命令
    • @Learner 我添加了一个更紧凑的解决方案
    • 我刚刚接受并喜欢您的回答。谢谢你
    猜你喜欢
    • 1970-01-01
    • 2016-12-14
    • 2015-06-16
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 2013-03-21
    • 2022-01-15
    • 2021-02-13
    相关资源
    最近更新 更多