按Cut对数据分组统计汇总
Stastistical summary of data group by Cut
我有数百个数据,提供从多篇研究论文中获得的不同年龄小动物的体重。我想按年龄对 7 天的体重进行分组和分析。我已经成功地使用 R 中的 cut 按年龄对数据进行分组,并在每个 7d bin 中具有默认值数(计数)。但即使经过大量谷歌搜索,我也找不到扩展 'cut' 以获得每个年龄段的基本统计摘要以包括均值、SE、CL 和中位数的方法。这可能吗?任何人都可以帮助或指出正确的方向吗?
我还查看了 dplyr,虽然它似乎能够提供统计摘要,但我看不到按 7d 间隔对年龄进行分组的方法。那会是更好的选择吗?
感谢非程序员的帮助。
附加信息
感谢你们两位的评论。很抱歉提供的信息有限,我希望这能澄清问题。我在 Excel 中有超过 2000 行数据。行是天数,列是 'MaleFI'、MaleMEI' 和 MaleBW,其中 FI 是食物摄入量,MEI 是可代谢能量摄入量,BW 是体重。部分数据如下图所示。通常我可以使用 Excel Pivot Table 来分析数据,但这不包括计算中位数或标准误差的选项; Power Pivot 可以但不分组!所以数据如下(按年龄天数排序,无空格):
- 年龄男性 FI MaleMEI 男性 BW
- 28.00 14.62 212.66 121.68
- 28.00 13.82 201.03 112.15
- 28.00 13.82 201.03 112.15
- 29.00 15.12 220.31 125.14 ...
年龄是连续的,最高可达 900 岁左右,每个年龄的值数量不同。
objective 是按 7d 周期分组,正如我提到的,对每个组进行统计分析,因此:
- 年龄男性FI男性MEI男性BW
- 21-28 均值均值均值
- SE SE SE
- 中位数中位数中位数
- 29-35 均值均值均值
- SE SE SE
- 中位数中位数中位数
- 36-42等
这是我用来对数据进行分组的代码,但正如我所提到的,事后看来,使用带有 group_by 的 dplyr 可能是更好的方法。
library("xlsx")
library("dplyr")
Pivot.data <- read.xlsx(file.choose(), 1) # read first sheet
pt<-cut(Pivot.data$Age, breaks=seq(21, 800, by=7))
table(pt)
输出是
(21,28] (28,35] (35,42] (42,49] (49,56] (56,63] (63,70] (70,77]
6 15 41 73 92 98 95 99
我对范围的格式很满意,即 (21,28] 等而不是 21-28。
感谢您的评论,很抱歉没有让要求更清楚。我很感激你放弃你的时间来帮助。
丹,这里是使用 dput 的输出:
dput(head(Pivot.data, 20))
structure(list(Age = c(28, 28, 28, 28, 28, 28, 30, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35, 35, 35), MaleFI = c(14.62, 13.82,
10.6691449814126, 15.9859154929577, 11.7, 14.0273778252258, 13.5877862595419,
17.73, 17.93, 17.99, 22.1214285714286, 17.6, 22.48, 21.7, 19.6,
21.4, 21.25, 20.37, 19.3215613382899, 23.169014084507), MaleMEI = c(212.66252,
201.02572, 144.342862453531, 216.273450704225, 160.171462269,
204.047711328562, 197.653240885495, 257.90058, 241.76812, 261.68254,
298.285342857143, 238.3216, 304.40168, 315.6482, 285.1016, 311.2844,
309.1025, 296.30202, 261.401403345724, 313.453591549295), MaleBW = c(121.68,
112.15, 85.7142857142856, 143.181818181818, 109.20245398773,
89.8187948576385, 126.522593320235, 131.96, 127.98, 142.57, 126.92,
146.9, 145.45, 131.9, 129.8, 132.4, 191.21, 179.44, 138.095238095238,
202.272727272727)), row.names = c(NA, 20L), class = "data.frame")
如果我理解正确(但请下次尝试包括一个可重现的例子),这段代码应该做:
library(tidyverse)
your_df %>%
# mutate(Age_cl = cut(Age, c(-Inf,30,60,Inf))) %>%
mutate(Age_cl = cut(Age, breaks=c(-Inf, seq(min(Age), max(Age), by=7), Inf), right = F)) %>%
group_by(Age_cl) %>%
summarise(
n=n(),
m=mean(Age, na.rm=T),
sd=sd(Age, na.rm=T),
max=max(Age, na.rm=T),
min=min(Age, na.rm=T)
)
您创建了新列 age_cl
,它是 cut
的结果,然后您按这个新列和 summarise
分组(或者您可以再次 mutate
,如你所愿)所有你想要的摘要。
您还可以将 summarise_at
与函数列表一起使用:
your_df %>%
mutate(Age_cl = cut(Age, c(-Inf,30,60,Inf))) %>%
group_by(Age_cl) %>%
summarise_at("Age", list(m=mean, sd=sd, max=max, min=min), na.rm=T)
请注意,其他参数将适用于所有函数,例如此处的 na.rm
。
编辑: 对于记录,似乎有一种方法可以使用 summary
函数,但您必须将其结果转换为 data.frame 让它工作。与像上面那样编写函数相比,这对于 summary
来说可能不值得。这是 iris
数据集的示例:
iris %>%
mutate(Sepal.Length_cl = cut(Sepal.Length, c(-Inf,5,6,Inf))) %>%
group_by(Sepal.Length_cl) %>%
group_modify(~summary(.$Sepal.Length) %>% unclass %>% t %>% as.data.frame)
我有数百个数据,提供从多篇研究论文中获得的不同年龄小动物的体重。我想按年龄对 7 天的体重进行分组和分析。我已经成功地使用 R 中的 cut 按年龄对数据进行分组,并在每个 7d bin 中具有默认值数(计数)。但即使经过大量谷歌搜索,我也找不到扩展 'cut' 以获得每个年龄段的基本统计摘要以包括均值、SE、CL 和中位数的方法。这可能吗?任何人都可以帮助或指出正确的方向吗?
我还查看了 dplyr,虽然它似乎能够提供统计摘要,但我看不到按 7d 间隔对年龄进行分组的方法。那会是更好的选择吗?
感谢非程序员的帮助。
附加信息
感谢你们两位的评论。很抱歉提供的信息有限,我希望这能澄清问题。我在 Excel 中有超过 2000 行数据。行是天数,列是 'MaleFI'、MaleMEI' 和 MaleBW,其中 FI 是食物摄入量,MEI 是可代谢能量摄入量,BW 是体重。部分数据如下图所示。通常我可以使用 Excel Pivot Table 来分析数据,但这不包括计算中位数或标准误差的选项; Power Pivot 可以但不分组!所以数据如下(按年龄天数排序,无空格):
- 年龄男性 FI MaleMEI 男性 BW
- 28.00 14.62 212.66 121.68
- 28.00 13.82 201.03 112.15
- 28.00 13.82 201.03 112.15
- 29.00 15.12 220.31 125.14 ...
年龄是连续的,最高可达 900 岁左右,每个年龄的值数量不同。
objective 是按 7d 周期分组,正如我提到的,对每个组进行统计分析,因此:
- 年龄男性FI男性MEI男性BW
- 21-28 均值均值均值
- SE SE SE
- 中位数中位数中位数
- 29-35 均值均值均值
- SE SE SE
- 中位数中位数中位数
- 36-42等
这是我用来对数据进行分组的代码,但正如我所提到的,事后看来,使用带有 group_by 的 dplyr 可能是更好的方法。
library("xlsx")
library("dplyr")
Pivot.data <- read.xlsx(file.choose(), 1) # read first sheet
pt<-cut(Pivot.data$Age, breaks=seq(21, 800, by=7))
table(pt)
输出是
(21,28] (28,35] (35,42] (42,49] (49,56] (56,63] (63,70] (70,77]
6 15 41 73 92 98 95 99
我对范围的格式很满意,即 (21,28] 等而不是 21-28。
感谢您的评论,很抱歉没有让要求更清楚。我很感激你放弃你的时间来帮助。
丹,这里是使用 dput 的输出:
dput(head(Pivot.data, 20)) structure(list(Age = c(28, 28, 28, 28, 28, 28, 30, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35), MaleFI = c(14.62, 13.82, 10.6691449814126, 15.9859154929577, 11.7, 14.0273778252258, 13.5877862595419, 17.73, 17.93, 17.99, 22.1214285714286, 17.6, 22.48, 21.7, 19.6, 21.4, 21.25, 20.37, 19.3215613382899, 23.169014084507), MaleMEI = c(212.66252, 201.02572, 144.342862453531, 216.273450704225, 160.171462269, 204.047711328562, 197.653240885495, 257.90058, 241.76812, 261.68254, 298.285342857143, 238.3216, 304.40168, 315.6482, 285.1016, 311.2844, 309.1025, 296.30202, 261.401403345724, 313.453591549295), MaleBW = c(121.68, 112.15, 85.7142857142856, 143.181818181818, 109.20245398773, 89.8187948576385, 126.522593320235, 131.96, 127.98, 142.57, 126.92, 146.9, 145.45, 131.9, 129.8, 132.4, 191.21, 179.44, 138.095238095238, 202.272727272727)), row.names = c(NA, 20L), class = "data.frame")
如果我理解正确(但请下次尝试包括一个可重现的例子),这段代码应该做:
library(tidyverse)
your_df %>%
# mutate(Age_cl = cut(Age, c(-Inf,30,60,Inf))) %>%
mutate(Age_cl = cut(Age, breaks=c(-Inf, seq(min(Age), max(Age), by=7), Inf), right = F)) %>%
group_by(Age_cl) %>%
summarise(
n=n(),
m=mean(Age, na.rm=T),
sd=sd(Age, na.rm=T),
max=max(Age, na.rm=T),
min=min(Age, na.rm=T)
)
您创建了新列 age_cl
,它是 cut
的结果,然后您按这个新列和 summarise
分组(或者您可以再次 mutate
,如你所愿)所有你想要的摘要。
您还可以将 summarise_at
与函数列表一起使用:
your_df %>%
mutate(Age_cl = cut(Age, c(-Inf,30,60,Inf))) %>%
group_by(Age_cl) %>%
summarise_at("Age", list(m=mean, sd=sd, max=max, min=min), na.rm=T)
请注意,其他参数将适用于所有函数,例如此处的 na.rm
。
编辑: 对于记录,似乎有一种方法可以使用 summary
函数,但您必须将其结果转换为 data.frame 让它工作。与像上面那样编写函数相比,这对于 summary
来说可能不值得。这是 iris
数据集的示例:
iris %>%
mutate(Sepal.Length_cl = cut(Sepal.Length, c(-Inf,5,6,Inf))) %>%
group_by(Sepal.Length_cl) %>%
group_modify(~summary(.$Sepal.Length) %>% unclass %>% t %>% as.data.frame)