首页 > 解决方案 > 如何在所有组合中使用 SD 求平均值

问题描述

我有这样的数据

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

这是我想要的方法是获取每行每两列之间的中位数或标准差,例如前两列 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

标签: rdplyrtidyr

解决方案


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

  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.

从宽格式,我们可以再次转换为“长”为

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.defaultfrombase R转换成listdata.frames的一个,转换成之后使用rowMediansfrommatrixStatsmatrix

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

推荐阅读