当前位置:首页 » 《关注互联网》 » 正文

R语言 数据分组汇总:求平均值、标准差、标准误

20 人参与  2024年10月22日 15:21  分类 : 《关注互联网》  评论

点击全文阅读


Summarizing data 汇总数据

当你想按组对数据进行汇总(包括平均值、标准差等)

这里介绍的三种方法可以根据某些指定变量对数据进行分组
并对每组应用汇总函数(如平均值、标准差等):

1、函数 ddply() ,来自 plyr 包,最容易使用的

2、函数 summarizeBy() ,来自 doBy 包,比较容易使用

3、函数 aggregate() ,来自R base 包,较难使用

示例数据
不同性别受试者,服用阿斯匹林或安慰剂前后的观测值以及变化差值
由性别和条件的组合来分组:F-安慰剂、F-阿司匹林、M-安慰剂和 M-阿司匹林
并希望计算出每个组的:
1) N(个体数)
2) mean of change(变化均值)
3) standard deviation(标准差)
4) standard error of the mean (均值标准误差)

data <- read.table(header=TRUE, text=' subject sex condition before after change       1   F   placebo   10.1   6.9   -3.2       2   F   placebo    6.3   4.2   -2.1       3   M   aspirin   12.4   6.3   -6.1       4   F   placebo    8.1   6.1   -2.0       5   M   aspirin   15.2   9.9   -5.3       6   F   aspirin   10.9   7.0   -3.9       7   F   aspirin   11.6   8.5   -3.1       8   M   aspirin    9.5   3.0   -6.5       9   F   placebo   11.5   9.0   -2.5      10   M   placebo   11.9  11.0   -0.9      11   F   aspirin   11.4   8.0   -3.4      12   M   aspirin   10.0   4.4   -5.6      13   M   aspirin   12.5   5.4   -7.1      14   M   placebo   10.6  10.6    0.0      15   M   aspirin    9.1   4.3   -4.8      16   F   placebo   12.1  10.2   -1.9      17   F   placebo   11.0   8.8   -2.2      18   F   placebo   11.9  10.2   -1.7      19   M   aspirin    9.1   3.6   -5.5      20   M   placebo   13.5  12.4   -1.1      21   M   aspirin   12.0   7.5   -4.5      22   F   placebo    9.1   7.6   -1.5      23   M   placebo    9.9   8.0   -1.9      24   F   placebo    7.6   5.2   -2.4      25   F   placebo   11.8   9.7   -2.1      26   F   placebo   11.8  10.7   -1.1      27   F   aspirin   10.1   7.9   -2.2      28   M   aspirin   11.6   8.3   -3.3      29   F   aspirin   11.3   6.8   -4.5      30   F   placebo   10.3   8.3   -2.0 ')

1、使用 ddply()

library(plyr)# ddply参数ddply(data, variables, fun = NULL, ... , progress = 'none' , drop = TRUE , parallel = FALSE)# - data : 要处理的数据框# - variables :分组变量,可以是公式,也可以是字符向量# - fun:处理分组数据的函数cdata <- ddply(data, c("sex", "condition"), summarise,               N    = length(change),    # 长度即总数               mean = mean(change),      # 求平均值               sd   = sd(change),        # 求标准差               se   = sd / sqrt(N)       # 求标准误)cdata#>   sex condition  N      mean        sd        se#> 1   F   aspirin  5 -3.420000 0.8642916 0.3865230#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867#> 3   M   aspirin  9 -5.411111 1.1307569 0.3769190#> 4   M   placebo  4 -0.975000 0.7804913 0.3902456

处理丢失的数据:
如果数据中有 NA 值,就需要设定参数 na.rm=TRUE
length() 没有 na.rm 这个选项,因此只能 sum(!is.na(...)) 来计算有多少个非 NA

# 先放一点NA值进来dataNA <- datadataNA$change[11:14] <- NAcdata <- ddply(dataNA, c("sex", "condition"), summarise,               N    = sum(!is.na(change)),                mean = mean(change, na.rm=TRUE),               sd   = sd(change, na.rm=TRUE),               se   = sd / sqrt(N))cdata#>   sex condition  N      mean        sd        se#> 1   F   aspirin  4 -3.425000 0.9979145 0.4989572#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867#> 3   M   aspirin  7 -5.142857 1.0674848 0.4034713#> 4   M   placebo  3 -1.300000 0.5291503 0.3055050

2、函数 summarizeBy()

library(doBy)cdata <- summaryBy(change ~ sex + condition, data=data, FUN=c(length,mean,sd))cdata#>   sex condition change.length change.mean change.sd#> 1   F   aspirin             5   -3.420000 0.8642916#> 2   F   placebo            12   -2.058333 0.5247655#> 3   M   aspirin             9   -5.411111 1.1307569#> 4   M   placebo             4   -0.975000 0.7804913# 重命名 change.length 这一列为 Nnames(cdata)[names(cdata)=="change.length"] <- "N"# 计算标准误cdata$change.se <- cdata$change.sd / sqrt(cdata$N)cdata#>   sex condition  N change.mean change.sd change.se#> 1   F   aspirin  5   -3.420000 0.8642916 0.3865230#> 2   F   placebo 12   -2.058333 0.5247655 0.1514867#> 3   M   aspirin  9   -5.411111 1.1307569 0.3769190#> 4   M   placebo  4   -0.975000 0.7804913 0.3902456

处理丢失数据:
na.rm=TRUE 可以传递给 summaryBy() 调用的每个函数,除了 length()

# 写一个新版本的 length 让它可以识别 na.rm=Tlength2 <- function (x, na.rm=FALSE) {    if (na.rm) sum(!is.na(x))    else       length(x)}dataNA <- datadataNA$change[11:14] <- NAcdataNA <- summaryBy(change ~ sex + condition, data=dataNA,                     FUN=c(length2, mean, sd), na.rm=TRUE)cdataNA#>   sex condition change.length2 change.mean change.sd#> 1   F   aspirin              4   -3.425000 0.9979145#> 2   F   placebo             12   -2.058333 0.5247655#> 3   M   aspirin              7   -5.142857 1.0674848#> 4   M   placebo              3   -1.300000 0.5291503

扩充:安排一步得出均值、计数、标准差、标准误和置信区间的函数summarySE
写函数:

## 对数据进行汇总## 得到 计数, 均值, 标准差, 标准误 和 置信区间 (95%).##   data: 数据框##   measurevar: 需要进行汇总的列##   groupvars: 提供分组的列##   na.rm: 一个布尔值,决定是否忽略NA##   conf.interval: 置信区间的百分比范围 (默认是 95%)summarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE,                      conf.interval=.95, .drop=TRUE) {    library(plyr)    # 一个新版本的 length 让它可以识别 na.rm=T    length2 <- function (x, na.rm=FALSE) {        if (na.rm) sum(!is.na(x))        else       length(x)    }    # 这一步开始汇总.    datac <- ddply(data, groupvars, .drop=.drop,      .fun = function(xx, col) {        c(N    = length2(xx[[col]], na.rm=na.rm),          mean = mean   (xx[[col]], na.rm=na.rm),          sd   = sd     (xx[[col]], na.rm=na.rm)        )      },      measurevar    )    # 重命名 均值 这一列     datac <- rename(datac, c("mean" = measurevar))    datac$se <- datac$sd / sqrt(datac$N)  # 计算标准误    # 标准误的置信区间乘数    # 计算置信区间的t统计量:     # 例如, 置信区间是.95, 则使用 .975 (高于/低于), 并使用 df=N-1    ciMult <- qt(conf.interval/2 + .5, datac$N-1)    datac$ci <- datac$se * ciMult    return(datac)}

示例计算:一部得到以上所有汇总信息

summarySE(data, measurevar="change", groupvars=c("sex", "condition"))#>   sex condition  N    change        sd        se        ci#> 1   F   aspirin  5 -3.420000 0.8642916 0.3865230 1.0731598#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867 0.3334201#> 3   M   aspirin  9 -5.411111 1.1307569 0.3769190 0.8691767#> 4   M   placebo  4 -0.975000 0.7804913 0.3902456 1.2419358# 当有 NA 值时, 使用 na.rm=TRUEsummarySE(dataNA, measurevar="change", groupvars=c("sex", "condition"), na.rm=TRUE)#>   sex condition  N    change        sd        se        ci#> 1   F   aspirin  4 -3.425000 0.9979145 0.4989572 1.5879046#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867 0.3334201#> 3   M   aspirin  7 -5.142857 1.0674848 0.4034713 0.9872588#> 4   M   placebo  3 -1.300000 0.5291503 0.3055050 1.3144821

用NA填充空白组合:
有时,汇总数据框中会出现空的因子组合,即有可能出现的因素组合,但实际上并没有出现在原始数据框架中。
在汇总数据框中自动用 NA 填入这些组合通常很有用。
为此,在调用 ddply()summarySE() 时设置 .drop=FALSE

用法示例:

# 首先把 男性+安慰剂 组合的数据删去dataSub <- subset(data, !(sex=="M" & condition=="placebo"))# 这样我们汇总数据时,男性+安慰剂 组合就会有空缺列summarySE(dataSub, measurevar="change", groupvars=c("sex", "condition"))#>   sex condition  N    change        sd        se        ci#> 1   F   aspirin  5 -3.420000 0.8642916 0.3865230 1.0731598#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867 0.3334201#> 3   M   aspirin  9 -5.411111 1.1307569 0.3769190 0.8691767# 设置 .drop=FALSE 不放弃这些组合summarySE(dataSub, measurevar="change", groupvars=c("sex", "condition"), .drop=FALSE)#> Warning in qt(conf.interval/2 + 0.5, datac$N - 1): NaNs produced#>   sex condition  N    change        sd        se        ci#> 1   F   aspirin  5 -3.420000 0.8642916 0.3865230 1.0731598#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867 0.3334201#> 3   M   aspirin  9 -5.411111 1.1307569 0.3769190 0.8691767#> 4   M   placebo  0       NaN        NA        NA        NA

用0填充空白组合:
原理同上,但改用0填充

写用0填充的函数:

fillMissingCombs <- function(df, factors, measures) {    # 列出因子level的组合列表    levelList <- list()    for (f in factors) {  levelList[[f]] <- levels(df[,f])  }        fullFactors <- expand.grid(levelList)        dfFull <- merge(fullFactors, df, all.x=TRUE)        # 如果测量值中有 NA ,就用 0 代替    for (m in measures) {      dfFull[is.na(dfFull[,m]), m] <- 0    }    return(dfFull)}

用法举例:

# 首先把 男性+安慰剂 组合的数据删去dataSub <- subset(data, !(sex=="M" & condition=="placebo"))cdataSub <- summarySE(dataSub, measurevar="change", groupvars=c("sex", "condition"))cdataSub#>   sex condition  N    change        sd        se        ci#> 1   F   aspirin  5 -3.420000 0.8642916 0.3865230 1.0731598#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867 0.3334201#> 3   M   aspirin  9 -5.411111 1.1307569 0.3769190 0.8691767# 用0填充空白组合fillMissingCombs(cdataSub, factors=c("sex","condition"), measures=c("N","change","sd","se","ci"))#>   sex condition  N    change        sd        se        ci#> 1   F   aspirin  5 -3.420000 0.8642916 0.3865230 1.0731598#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867 0.3334201#> 3   M   aspirin  9 -5.411111 1.1307569 0.3769190 0.8691767#> 4   M   placebo  0  0.000000 0.0000000 0.0000000 0.0000000

3、使用R自带的aggregate()

缺点是步骤较为繁琐
优点是不用安装新的R包

# 统计每个类别(性别*条件)中的受试者人数cdata <- aggregate(data["subject"], by=data[c("sex","condition")], FUN=length)cdata#>   sex condition subject#> 1   F   aspirin       5#> 2   M   aspirin       9#> 3   F   placebo      12#> 4   M   placebo       4# 重命名 "subject" 这一列为 "N"names(cdata)[names(cdata)=="subject"] <- "N"cdata#>   sex condition  N#> 1   F   aspirin  5#> 2   M   aspirin  9#> 3   F   placebo 12#> 4   M   placebo  4# 按 sex 排序cdata <- cdata[order(cdata$sex),]cdata#>   sex condition  N#> 1   F   aspirin  5#> 3   F   placebo 12#> 2   M   aspirin  9#> 4   M   placebo  4# 同时保留 __before__ 和 __after__ 这两列:# 按性别和条件获取平均效应大小cdata.means <- aggregate(data[c("before","after","change")],                          by = data[c("sex","condition")], FUN=mean)cdata.means#>   sex condition   before     after    change#> 1   F   aspirin 11.06000  7.640000 -3.420000#> 2   M   aspirin 11.26667  5.855556 -5.411111#> 3   F   placebo 10.13333  8.075000 -2.058333#> 4   M   placebo 11.47500 10.500000 -0.975000# 合并数据框cdata <- merge(cdata, cdata.means)cdata#>   sex condition  N   before     after    change#> 1   F   aspirin  5 11.06000  7.640000 -3.420000#> 2   F   placebo 12 10.13333  8.075000 -2.058333#> 3   M   aspirin  9 11.26667  5.855556 -5.411111#> 4   M   placebo  4 11.47500 10.500000 -0.975000# 获取 "change"的样本 (n-1) 标准差cdata.sd <- aggregate(data["change"],                      by = data[c("sex","condition")], FUN=sd)# 重命名为 change.sdnames(cdata.sd)[names(cdata.sd)=="change"] <- "change.sd"cdata.sd#>   sex condition change.sd#> 1   F   aspirin 0.8642916#> 2   M   aspirin 1.1307569#> 3   F   placebo 0.5247655#> 4   M   placebo 0.7804913# 合并cdata <- merge(cdata, cdata.sd)cdata#>   sex condition  N   before     after    change change.sd#> 1   F   aspirin  5 11.06000  7.640000 -3.420000 0.8642916#> 2   F   placebo 12 10.13333  8.075000 -2.058333 0.5247655#> 3   M   aspirin  9 11.26667  5.855556 -5.411111 1.1307569#> 4   M   placebo  4 11.47500 10.500000 -0.975000 0.7804913# 最后计算标准误cdata$change.se <- cdata$change.sd / sqrt(cdata$N)cdata#>   sex condition  N   before     after    change change.sd change.se#> 1   F   aspirin  5 11.06000  7.640000 -3.420000 0.8642916 0.3865230#> 2   F   placebo 12 10.13333  8.075000 -2.058333 0.5247655 0.1514867#> 3   M   aspirin  9 11.26667  5.855556 -5.411111 1.1307569 0.3769190#> 4   M   placebo  4 11.47500 10.500000 -0.975000 0.7804913 0.3902456

如果数据中有NA值并希望忽略它们,设置 na.rm=TRUE

cdata.means <- aggregate(data[c("before","after","change")],                          by = data[c("sex","condition")],                         FUN=mean, na.rm=TRUE)cdata.means#>   sex condition   before     after    change#> 1   F   aspirin 11.06000  7.640000 -3.420000#> 2   M   aspirin 11.26667  5.855556 -5.411111#> 3   F   placebo 10.13333  8.075000 -2.058333#> 4   M   placebo 11.47500 10.500000 -0.975000

点击全文阅读


本文链接:http://m.zhangshiyu.com/post/175544.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1