我有一个数据框架,我需要计算每组(即每月,如下)的平均值。

Name     Month  Rate1     Rate2
Aira       1      12        23
Aira       2      18        73
Aira       3      19        45
Ben        1      53        19
Ben        2      22        87
Ben        3      19        45
Cat        1      22        87
Cat        2      67        43
Cat        3      45        32

我想要的输出如下所示,其中Rate1和Rate2的值是组均值。请忽略这个值,我已经为这个例子编好了。

Name       Rate1       Rate2
Aira        23.21       12.2
Ben         45.23       43.9
Cat         33.22       32.2

当前回答

你也可以使用package plyr,它在某种程度上更通用:

library(plyr)

ddply(d, .(Name), summarize,  Rate1=mean(Rate1), Rate2=mean(Rate2))

  Name    Rate1    Rate2
1 Aira 16.33333 47.00000
2  Ben 31.33333 50.33333
3  Cat 44.66667 54.00000

其他回答

一个选项是使用包数据。表,它也有类data.frame,但是像你正在寻找的操作计算得更快。

library(data.table)
mydt <- structure(list(Name = c("Aira", "Aira", "Aira", "Ben", "Ben", "Ben", "Cat", "Cat", "Cat"), Month = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), Rate1 = c(15.6396600443877, 2.15649279424609, 6.24692918928743, 2.37658797276116, 34.7500663272292, 3.28750138697048, 29.3265553981065, 17.9821839334431, 10.8639802575958), Rate2 = c(17.1680489538369, 5.84231656330206, 8.54330866437461, 5.88415184986176, 3.02064294862551, 17.2053351400752, 16.9552950199166, 2.56058000170089, 15.7496228048122)), .Names = c("Name", "Month", "Rate1", "Rate2"), row.names = c(NA, -9L), class = c("data.table", "data.frame"))

现在对每个人(姓名)取所有3个月的Rate1和Rate2的平均值: 首先,决定你要取哪些列的均值

colstoavg <- names(mydt)[3:4]

现在我们用lapply对列求平均值我们要求avg (colstoavg)

mydt.mean <- mydt[,lapply(.SD,mean,na.rm=TRUE),by=Name,.SDcols=colstoavg]

 mydt.mean
   Name     Rate1     Rate2
1: Aira  8.014361 10.517891
2:  Ben 13.471385  8.703377
3:  Cat 19.390907 11.755166

你也可以使用sqldf包来完成,如下所示:

library(sqldf)

x <- read.table(text='Name     Month  Rate1     Rate2
Aira       1      12        23
                Aira       2      18        73
                Aira       3      19        45
                Ben        1      53        19
                Ben        2      22        87
                Ben        3      19        45
                Cat        1      22        87
                Cat        2      67        43
                Cat        3      45        32', header=TRUE)

sqldf("
select 
  Name
  ,avg(Rate1) as Rate1_float
  ,avg(Rate2) as Rate2_float
  ,avg(Rate1) as Rate1
  ,avg(Rate2) as Rate2
from x
group by 
  Name
")

#  Name Rate1_float Rate2_float Rate1 Rate2
#1 Aira    16.33333    47.00000    16    47
#2  Ben    31.33333    50.33333    31    50
#3  Cat    44.66667    54.00000    44    54

正如其他答案所示,我最近转向了dplyr,但sqldf很好,因为大多数数据分析师/数据科学家/开发人员至少在SQL方面有一定的流畅性。通过这种方式,我认为它比dplyr或上面介绍的其他解决方案更易于编写具有普遍可读性的代码。

更新:在回复下面的注释时,我尝试按上面所示更新代码。然而,这种行为并不像我预期的那样。似乎只有当列别名与原始列名匹配时,列定义(即int vs float)才会继续执行。指定新名称时,将不舍入地返回聚合列。

或者使用dplyr包中的group_by & summarise_at:

library(dplyr)

d %>%
  group_by(Name) %>%
  summarise_at(vars(-Month), funs(mean(., na.rm=TRUE)))

# A tibble: 3 x 3
  Name  Rate1 Rate2
  <fct> <dbl> <dbl>
1 Aira   16.3  47.0
2 Ben    31.3  50.3
3 Cat    44.7  54.0

参见?summarise_at,了解指定要执行的变量的多种方法。这里,vars(-Month)表示除Month之外的所有变量。


在tidyverse/dplyr的最新版本中,使用summarise(across(…))比summarise_at更可取:

d %>% 
  group_by(Name) %>%
  summarise(across(-Month, mean, na.rm = TRUE))

我描述了两种方法,一种基于数据。表和其他基于reshape2的包。数据。表的方式已经有了一个答案,但我已经试图使它更清晰和更详细。

数据是这样的:

 d <- structure(list(Name = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 
3L, 3L), .Label = c("Aira", "Ben", "Cat"), class = "factor"), 
    Month = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), Rate1 = c(12L, 
    18L, 19L, 53L, 22L, 19L, 22L, 67L, 45L), Rate2 = c(23L, 73L, 
    45L, 19L, 87L, 45L, 87L, 43L, 32L)), .Names = c("Name", "Month", 
"Rate1", "Rate2"), class = "data.frame", row.names = c(NA, -9L
))
head(d)
  Name Month Rate1 Rate2
1 Aira     1    12    23
2 Aira     2    18    73
3 Aira     3    19    45
4  Ben     1    53    19
5  Ben     2    22    87
6  Ben     3    19    45


library("reshape2")
mym <- melt(d, id = c("Name"))
res <- dcast(mym, Name ~ variable, mean)
res
#Name Month    Rate1    Rate2
#1 Aira     2 16.33333 47.00000
#2  Ben     2 31.33333 50.33333
#3  Cat     2 44.66667 54.00000

使用data.table:

# At first, I convert the data.frame to data.table and then I group it 
setDT(d)
d[, .(Rate1 = mean(Rate1), Rate2 = mean(Rate2)), by = .(Name)]
#   Name    Rate1    Rate2
#1: Aira 16.33333 47.00000
#2:  Ben 31.33333 50.33333
#3:  Cat 44.66667 54.00000

还有另一种方法,避免在data中为j写很多参数。表使用。sd

d[, lapply(.SD, mean), by = .(Name)]
#   Name Month    Rate1    Rate2
#1: Aira     2 16.33333 47.00000
#2:  Ben     2 31.33333 50.33333
#3:  Cat     2 44.66667 54.00000

如果我们只想要Rate1和Rate2,那么我们可以像下面这样使用. sdcol:

d[, lapply(.SD, mean), by = .(Name), .SDcols = 3:4]
#  Name    Rate1    Rate2
#1: Aira 16.33333 47.00000
#2:  Ben 31.33333 50.33333
#3:  Cat 44.66667 54.00000

你也可以使用泛型函数cbind()和lm()而不截取:

cbind(lm(d$Rate1~-1+d$Name)$coef,lm(d$Rate2~-1+d$Name)$coef)
>               [,1]     [,2]
>d$NameAira 16.33333 47.00000
>d$NameBen  31.33333 50.33333
>d$NameCat  44.66667 54.00000