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