重点关注数据分析

从此告别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语言数据分析指南,持续分享数据可视化的经典案例及一些生信知识,希望对大家有所帮助

上一篇下一篇

猜你喜欢

热点阅读