从列中计算 mean/std/ci

calc mean/std/ci from column

是否有一个包可以轻松计算每个特定的 n 个数字 mean/std/ci。 在以数据开头的示例中:

> n = c(0,0,0,0,0,0,0,2,2,2,2,5,5,5,5,8,8,8,8)
> s = c(43,23,65,43,12,54,43,12,2,43,62,25,55,75,95,28,48,68,18)
> df = data.frame(n, s)
> df
   n  s
1  0 43
2  0 23
3  0 65
4  0 43
5  0 12
6  0 54
7  0 43
8  2 12
9  2  2
10 2 43
11 2 62
12 5 25
13 5 55
14 5 75
15 5 95
16 8 28
17 8 48
18 8 68
19 8 18

结果为:

data
n mean std ci
0 40   ..  ..
2 30   ..  ..
5 63   ..  ..
8 41   ..  ..

您可以使用 dplyr 包。

这是一个代码片段。请注意,我假设您想使用 95% 级别的标准正态近似来构建置信区间,但您可以做出任何您喜欢的选择。

n = c(0,0,0,0,0,0,0,2,2,2,2,5,5,5,5,8,8,8,8)
s = c(43,23,65,43,12,54,43,12,2,43,62,25,55,75,95,28,48,68,18)
df = data.frame(n, s)

  df %>%
  group_by(n) %>%
  summarise(mean = mean(s),
            std = sqrt(var(s)),
            lower = mean(s) - qnorm(.975)*std/sqrt(n()),
            upper = mean(s) + qnorm(.975)*std/sqrt(n()))

Source: local data frame [4 x 5]

  n     mean      std     lower    upper
1 0 40.42857 17.88721 27.177782 53.67936
2 2 29.75000 27.69326  2.611104 56.88890
3 5 62.50000 29.86079 33.236965 91.76303
4 8 40.50000 22.17356 18.770313 62.22969

dplyr 很好,但不是必需的。在基数 R 中:

 ## df() is built-in in R, avoid ...
 dd <- data.frame(n=rep(c(0,2,5,8),c(7,4,4,4)),
              s = c(43,23,65,43,12,54,43,12,2,43,
                  62,25,55,75,95,28,48,68,18))
 sumfun <- function(x) {
     m <- mean(x)
     s <- sd(x)
     se <- s/sqrt(length(x))
     c(mean=m,sd=s,lwr=m-1.96*se,upr=m+1.96*se)
 }

(或从 Hmisc 包中查看 smean.cl.normal()smean.cl.boot() 等...)

 res <- do.call(rbind,tapply(dd$s,dd$n,sumfun))
 res <- cbind(n=unique(dd$n),as.data.frame(res))

或者正如@thelatemail 指出的那样:

 res <- do.call(data.frame,aggregate(s ~ n, data=df, FUN=sumfun ))

如果您打算定期使用它,您可以轻松地将它打包成一个函数。

对于较大的数据 sets/more 复杂转换,您可以搜索 SO 以比较 dplyrplyrdata.tabledoBy 包中的解决方案作为答案以及使用 tapply()ave()aggregate()by() ...

组合的 base-R 解决方案

谢谢大家的指点,我看了plyr解决了:

n = c(0,0,0,0,0,0,0,2,2,2,2,5,5,5,5,8,8,8,8)
s = c(43,23,65,43,12,54,43,12,2,43,62,25,55,75,95,28,48,68,18)
dd = data.frame(n, s)

library(plyr)
data <- ddply(dd,.(n),function(dd) c(mean=mean(dd$s),
                                    std = sd(dd$s),
                                    se = sd(dd$s)/sqrt(length(dd$s)),
                                    lower = mean(dd$s)-qnorm(.975)*sd(dd$s)/sqrt(length(dd$s)),
                                    upper = mean(dd$s)+qnorm(.975)*sd(dd$s)/sqrt(length(dd$s))
                                    ))

结果为:

    data
  n     mean      std        se     lower    upper
1 0 40.42857 17.88721  6.760731 27.177782 53.67936
2 2 29.75000 27.69326 13.846630  2.611104 56.88890
3 5 62.50000 29.86079 14.930394 33.236965 91.76303
4 8 40.50000 22.17356 11.086779 18.770313 62.22969

以后会避免 df(),谢谢

更新 tidyr 1.0.0

尽管@user1357015 的解决方案完全没问题,但如果你像我一样是 tidyverse 的粉丝,还有一个优雅的选择:

新的 tidyr 1.0.0 包含一个没有引起太多关注但非常有用的功能:unnest_wider。 这样,您可以将代码简化为以下内容:

df %>% 
  group_by(n) %>% 
  nest(data = -"n") %>% 
  mutate(ci = map(data, ~ MeanCI(.x$s))) %>% 
  unnest_wider(ci)

这给出了

# A tibble: 4 x 5
# Groups:   n [4]
      n data              mean lwr.ci upr.ci
  <dbl> <list>           <dbl>  <dbl>  <dbl>
1     0 <tibble [7 × 1]>  40.4  23.9    57.0
2     2 <tibble [4 × 1]>  29.8 -14.3    73.8
3     5 <tibble [4 × 1]>  62.5  15.0   110. 
4     8 <tibble [4 × 1]>  40.5   5.22   75.8