重点关注数据分析

从此告别Excel使用tidyverse按分组处理数据

2021-06-08  本文已影响0人  R语言数据分析指南

本节来介绍如何通过tidyverse对数据按分组求均值,喜欢的小伙伴欢迎关注我获取数据

library(tidyverse)
library(magrittr)

首先通过iris数据集进行演示

iris %>% as_tibble() %>%
  group_by(Species) %>%
  summarise(across(where(is.numeric), ~ sum(.x, na.rm=TRUE)))
  Species    Sepal.Length Sepal.Width Petal.Length Petal.Width
  <fct>             <dbl>       <dbl>        <dbl>       <dbl>
1 setosa             250.        171.         73.1        12.3
2 versicolor         297.        138.        213          66.3
3 virginica          329.        149.        278.        101. 

可以看到处理过程非常的简单,但是用我们自己的数据集该如何进行操作那?

通常我们自己的数据,数据集和分组文件一般是分开的,因此我们如果需要按分组求和首先就需要将2个文件整合为一个文件

读入数据

otu <- read.delim("otu.xls",check.names = F)
group <- read.delim("group.xls")

按分组求和

otu %>% left_join(.,group,by="sample") %>% 
  select(sample,group,everything()) %>%
  pivot_longer(-c(sample,group)) %>% 
  group_by(group,name) %>%
  summarise(sum=sum(value),.groups = 'drop') %>% 
  pivot_wider(names_from=name, values_from=sum)
 group Armatimonadetes Bacteroidetes Caldiserica Chlamydiae Chlorobi
  <chr>           <dbl>         <dbl>       <dbl>      <dbl>    <dbl>
1 CON          0.00250           6.81  0.00000805      0.184 0.000684
2 TREAT        0.000123          6.75  0.000227        0.128 0.000465
# … with 22 more variables: Chloroflexi <dbl>, Chrysiogenetes <dbl>,
#   Cyanobacteria <dbl>, Deferribacteres <dbl>,
#   Deinococcus-Thermus <dbl>, Elusimicrobia <dbl>, Fibrobacteres <dbl>,
#   Firmicutes <dbl>, Fusobacteria <dbl>, Gemmatimonadetes <dbl>,
#   Ignavibacteria <dbl>, Lentisphaerae <dbl>, Nitrospirae <dbl>,
#   PhylaUnknown <dbl>, Planctomycetes <dbl>, Proteobacteria <dbl>,
#   Spirochaetae <dbl>, Spirochaetes <dbl>, Synergistetes <dbl>,
#   Tenericutes <dbl>, Thermotogae <dbl>, Verrucomicrobia <dbl>

across来进行分组求和

通过across函数可以省略宽表转长表的步骤

otu %>% left_join(.,group,by="sample") %>% 
  select(sample,group,everything()) %>%
  group_by(group) %>%
  summarise(across(where(is.numeric), ~ sum(.x, na.rm=TRUE))) %>% 
  column_to_rownames("group") %>% t() %>% as.data.frame() %>% 
  rownames_to_column("otu")
                   otu          CON        TREAT
1      Armatimonadetes  0.002498694  0.000122575
2        Bacteroidetes  6.807462087  6.749612659
3          Caldiserica  0.000008050  0.000227317
4           Chlamydiae  0.183542770  0.128444178
5             Chlorobi  0.000684476  0.000465390
6          Chloroflexi  0.019397120  0.020808506
7       Chrysiogenetes  0.000008050  0.000000000

最后在介绍通过for循环来按分组求均值的一个案例

data <- data.frame(A1=1:10,A2=11:20,A3=12:21,
                   B2=80:89,B1=12:21,B3=15:24)
data
   A1 A2 A3 B2 B1 B3
1   1 11 12 80 12 15
2   2 12 13 81 13 16
3   3 13 14 82 14 17
4   4 14 15 83 15 18
5   5 15 16 84 16 19
6   6 16 17 85 17 20
7   7 17 18 86 18 21
8   8 18 19 87 19 22
9   9 19 20 88 20 23
10 10 20 21 89 21 24
result <- list(); b <- 3
for (i in 1:(data %>% ncol() / b)) {
  result[[i]] <- data %>%
    select((b * i - b + 1):(b * i) %>% all_of()) %>%
    apply(1, mean)
}

result %>% as.data.frame() %>% 
  set_colnames(c("A","B"))
    A        B
1   8 35.66667
2   9 36.66667
3  10 37.66667
4  11 38.66667
5  12 39.66667
6  13 40.66667
7  14 41.66667
8  15 42.66667
9  16 43.66667
10 17 44.66667

可以看到上面的代码也挺简洁的,但是有一个条件就是每一组的样本数目要一致才能使用循环,因此使用across来对数据进行分组处理也有一定的存在的意义

data %>% t() %>% as.data.frame() %>% 
  mutate(group=rep(LETTERS[1:2],times=c(3,3))) %>%
  group_by(group) %>%
  summarise(across(where(is.numeric), ~ mean(.x, na.rm=TRUE))) %>% 
  column_to_rownames("group") %>% t() %>% as.data.frame()
     A        B
V1   8 35.66667
V2   9 36.66667
V3  10 37.66667
V4  11 38.66667
V5  12 39.66667
V6  13 40.66667
V7  14 41.66667
V8  15 42.66667
V9  16 43.66667
V10 17 44.66667

喜欢的小伙伴欢迎关注我的公众号

R语言数据分析指南,持续分享数据可视化的经典案例及一些生信知识,希望对大家有所帮助

上一篇 下一篇

猜你喜欢

热点阅读