如何在R中计算数据框中每个分组的均值/中位数

17

我有一个数据框记录了客户的详细消费金额,如下所示:

custid, value
1,  1
1,  3
1,  2
1,  5
1,  4
1,  1
2,  1
2,  10
3,  1
3,  2
3,  5
怎样使用平均值、最大值、中位数、标准差等计算特征?需要使用一些 apply 函数吗?如何操作?
custid, mean, max,min,median,std
1,  ....
2,....
3,....
5个回答

24
library(dplyr)
dat%>%
group_by(custid)%>% 
summarise(Mean=mean(value), Max=max(value), Min=min(value), Median=median(value), Std=sd(value))
#  custid     Mean Max Min Median      Std
#1      1 2.666667   5   1    2.5 1.632993
#2      2 5.500000  10   1    5.5 6.363961
#3      3 2.666667   5   1    2.0 2.081666

针对更大的数据集,data.table 会更快。

setDT(dat)[,list(Mean=mean(value), Max=max(value), Min=min(value), Median=as.numeric(median(value)), Std=sd(value)), by=custid]
#   custid     Mean Max Min Median      Std
#1:      1 2.666667   5   1    2.5 1.632993
#2:      2 5.500000  10   1    5.5 6.363961
#3:      3 2.666667   5   1    2.0 2.081666

20

除此之外,这里还有“doBy”包中的summaryBy函数可供选择,你可以在其中指定要应用的list函数。

library(doBy)
summaryBy(value ~ custid, data = mydf, 
          FUN = list(mean, max, min, median, sd))
#   custid value.mean value.max value.min value.median value.sd
# 1      1   2.666667         5         1          2.5 1.632993
# 2      2   5.500000        10         1          5.5 6.363961
# 3      3   2.666667         5         1          2.0 2.081666
当然,您也可以坚持使用基本的R语言:
myFun <- function(x) {
  c(min = min(x), max = max(x), 
    mean = mean(x), median = median(x), 
    std = sd(x))
}

tapply(mydf$value, mydf$custid, myFun)
# $`1`
#      min      max     mean   median      std 
# 1.000000 5.000000 2.666667 2.500000 1.632993 
# 
# $`2`
#       min       max      mean    median       std 
#  1.000000 10.000000  5.500000  5.500000  6.363961 
# 
# $`3`
#      min      max     mean   median      std 
# 1.000000 5.000000 2.666667 2.000000 2.081666 

cbind(custid = unique(mydf$custid), 
      do.call(rbind, tapply(mydf$value, mydf$custid, myFun)))
#   custid min max     mean median      std
# 1      1   1   5 2.666667    2.5 1.632993
# 2      2   1  10 5.500000    5.5 6.363961
# 3      3   1   5 2.666667    2.0 2.081666

9

如果你想对所有或同一列使用更多的函数,可以使用dplyr中的summarise_eachmutate_each

require(dplyr)
dat %>%
  group_by(custid) %>%
  summarise_each(funs(max, min, mean, median, sd), value)
#Source: local data frame [3 x 6]
#
#  custid max min     mean median       sd
#1      1   5   1 2.666667    2.5 1.632993
#2      2  10   1 5.500000    5.5 6.363961
#3      3   5   1 2.666667    2.0 2.081666

或者使用基于R的aggregate的另一种选项:

aggregate(value ~ custid, data = dat, summary)
#  custid value.Min. value.1st Qu. value.Median value.Mean value.3rd Qu. value.Max.
#1      1      1.000         1.250        2.500      2.667         3.750      5.000
#2      2      1.000         3.250        5.500      5.500         7.750     10.000
#3      3      1.000         1.500        2.000      2.667         3.500      5.000

(这不包括标准差,但我认为这是用于其他描述性统计的不错方法。)

关于此事的最新消息是,该函数返回以下信息:summarise_each()已被弃用。请改用summarise_all()summarise_at()summarise_if()。要在一组变量上映射funs,请使用summarise_at() - Alf Pascu

8

我喜欢来自 psych 包的 describeBy() 函数。就像这样:

df <- structure(list(custid. = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 3L, 
3L, 3L), value = c(1L, 3L, 2L, 5L, 4L, 1L, 1L, 10L, 1L, 2L, 5L
)), .Names = c("custid.", "value"), class = "data.frame", row.names = c(NA, 
-11L))
df
       custid. value
1        1     1
2        1     3
3        1     2
4        1     5
5        1     4
6        1     1
7        2     1
8        2    10
9        3     1
10       3     2
11       3     5
# install.packages(c("psych"), dependencies = TRUE)
require(psych)

 describeBy(df$value, df$custid.)
group: 1
  vars n mean   sd median trimmed  mad min max range skew kurtosis   se
1    1 6 2.67 1.63    2.5    2.67 2.22   1   5     4 0.21    -1.86 0.67
----------------------------------------------------------------------- 
group: 2
  vars n mean   sd median trimmed  mad min max range skew kurtosis  se
1    1 2  5.5 6.36    5.5     5.5 6.67   1  10     9    0    -2.75 4.5
----------------------------------------------------------------------- 
group: 3
  vars n mean   sd median trimmed  mad min max range skew kurtosis  se
1    1 3 2.67 2.08      2    2.67 1.48   1   5     4 0.29    -2.33 1.2

如果您更喜欢,也可以将其作为矩阵获取:

 describeBy(df$value, df$custid., mat=T, skew = F)
   item group1 vars n     mean       sd median min max range        se
11    1      1    1 6 2.666667 1.632993    2.5   1   5     4 0.6666667
12    2      2    1 2 5.500000 6.363961    5.5   1  10     9 4.5000000
13    3      3    1 3 2.666667 2.081666    2.0   1   5     4 1.2018504

@AnandaMahto,太快了。对不起。我已经更新了我的答案。 - Eric Fail

6
你可以使用 plyr 包。
分裂应用组合策略。
ddply (数据框, .(分组列), 函数)。
在你的情况下,
ddply (数据框, .(客户 ID), summarize, "mean" = 平均值(value), "median" = 中位数(value))。
查看 ddply 帮助文档,里面有一个很好的例子可供参考。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接