R列按因子平均值

R列按因子平均值,r,R,我有这样的数据集 data name v1 v2 v3 v4 v5 a 1 2 7 9 3 b 3 8 6 4 8 c 2 5 0 1 9 a 6 0 6 2 1 c 3 9 4 7 5 name是一个因子变量。我想通过因子data$name计算v2、v3、v4、v5的平均值。我使用了下面的命令,但它不起作用 tapply(data[,3:6],data$name,mean)

我有这样的数据集

data
name v1  v2  v3  v4  v5
a    1   2   7   9   3
b    3   8   6   4   8
c    2   5   0   1   9
a    6   0   6   2   1
c    3   9   4   7   5
name
是一个因子变量。我想通过因子
data$name
计算
v2、v3、v4、v5
的平均值。我使用了下面的命令,但它不起作用

tapply(data[,3:6],data$name,mean)
现在,我使用了以下代码

newdata<-0
for (name in unique(data$name)){
    rowIndex <- which(data$name == name)
    result <- colMeans(data[rowIndex,])
    newdata[name,]<-result
}

newdataEdit:原始答案没有给出正确的结果。这似乎工作正常(选择(-variable)可避免有额外的列,但不需要其他列)

使用dplyr和REGRAPE2软件包:

library(reshape2)
library(dplyr)
data %>% 
 select(-v1) %>%
 melt %>% 
 group_by(name) %>% 
 select(-variable) %>% 
 summarise_each(funs(mean))
# Source: local data frame [3 x 2]
# 
#   name value
# 1    a  3.75
# 2    b  6.50
# 3    c  5.00
library(dplyr)
library(tidyr)

data %>% gather(name, value, v2:v5) %>%
    group_by(name) %>% summarize(average=mean(value))
#   name average
# 1    a    3.75
# 2    b    6.50
# 3    c    5.00

根据预期结果显示:

即系数a的预期结果为(2+7+9+3)+(0+6+2+1)/8

还有一种方法

library(data.table)
cols <- paste0("v", 2:5) # set the columns you want to operate on
setDT(data)[, Sums := rowSums(.SD), .SDcols = cols]
data[, list(Means = sum(Sums)/(.N*length(cols))), by = name]
##    name Means
## 1:    a  3.75
## 2:    b  6.50
## 3:    c  5.00
或者按照@Anandas的建议

library(reshape2)
melt(setDT(data), id.vars = "name", measure.vars = cols)[, mean(value), by = name]
##    name   V1
## 1:    a 3.75
## 2:    b 6.50
## 3:    c 5.00

这可以通过dplyr和tidyr软件包的组合来实现:

library(reshape2)
library(dplyr)
data %>% 
 select(-v1) %>%
 melt %>% 
 group_by(name) %>% 
 select(-variable) %>% 
 summarise_each(funs(mean))
# Source: local data frame [3 x 2]
# 
#   name value
# 1    a  3.75
# 2    b  6.50
# 3    c  5.00
library(dplyr)
library(tidyr)

data %>% gather(name, value, v2:v5) %>%
    group_by(name) %>% summarize(average=mean(value))
#   name average
# 1    a    3.75
# 2    b    6.50
# 3    c    5.00

这是因为
gather
v2:v5
列合并到一个列中,可以直观地将它们分组:

data %>% gather(name, value, v2:v5)
#    name v1 name value
# 1     a  1   v2     2
# 2     b  3   v2     8
# 3     c  2   v2     5
# 4     a  6   v2     0
# 5     c  3   v2     9
# 6     a  1   v3     7
# ...

所有答案都很好,但我只想补充一点:

data <- data.frame(name=as.factor(c("a","b","c","a","c")),
                   v1=c(1,3,2,6,3),
                   v2=c(2,8,5,0,9),
                   v3=c(7,6,0,6,4),
                   v4=c(9,4,1,2,7),
                   v5=c(3,8,9,1,5))

u.id <- unique(data$name)
newdata <- t(sapply(unique(u.id),function(c.id){
    colMeans(data[data$name == c.id,-1])
}))
rownames(newdata) <- u.id

newdata

  v1  v2  v3  v4 v5
a 3.5  1 6.5 5.5  2
b 3.0  8 6.0 4.0  8
c 2.5  7 2.0 4.0  7

数据尝试
库(data.table);setDT(data)[,lappy(.SD,mean),by=name,.SDcols=paste0(“v”,2:5)]
(尚未测试)示例代码不起作用。你能发布你的预期结果吗?我已经在问题中添加了预期结果。这不会给出预期的结果哦,上帝。你说得对@DavidArenburg。下次必须更加小心(再次…)。好的,已经修改了答案,现在可以了。不过,我不确定这有多流畅……谢谢您的编辑@DavidArenburg,现在看起来好多了。@David Arenburg感谢我为您提供了+1的data.table代码。我猜
4
是ncol(数据),对吗?是的。。它不像你的一般。我想在开始时预先定义列名,然后使其更通用。分别编辑了它的
堆栈的位置
未列出的位置
?不要让他们觉得自己被边缘化了:-)@Ananda Mahto我本来想尝试
unlist
,但不知怎的,我最终得到了
c
:-)@Ananda Mahto感谢您的建议,这是我尝试使用的方法之一。我不知道
.SD
melt
之间的权衡,但是
melt(setDT(data),id.vars=“name”,measure.vars=cols)[平均值(value),by=name]
也许?或者
数据[,平均值(c(v2,v3,v4,v5)),by=name]
。如果有更多的列,我们可以构造一个表达式并对其求值。@Arun,这很好。我试图这样做,但在列名方面有问题。可能是因为我使用了
粘贴
,它们被引用了
library(dplyr)
library(tidyr)

data %>% gather(name, value, v2:v5) %>%
    group_by(name) %>% summarize(average=mean(value))
#   name average
# 1    a    3.75
# 2    b    6.50
# 3    c    5.00
data %>% gather(name, value, v2:v5)
#    name v1 name value
# 1     a  1   v2     2
# 2     b  3   v2     8
# 3     c  2   v2     5
# 4     a  6   v2     0
# 5     c  3   v2     9
# 6     a  1   v3     7
# ...
data <- data.frame(name=as.factor(c("a","b","c","a","c")),
                   v1=c(1,3,2,6,3),
                   v2=c(2,8,5,0,9),
                   v3=c(7,6,0,6,4),
                   v4=c(9,4,1,2,7),
                   v5=c(3,8,9,1,5))

u.id <- unique(data$name)
newdata <- t(sapply(unique(u.id),function(c.id){
    colMeans(data[data$name == c.id,-1])
}))
rownames(newdata) <- u.id

newdata

  v1  v2  v3  v4 v5
a 3.5  1 6.5 5.5  2
b 3.0  8 6.0 4.0  8
c 2.5  7 2.0 4.0  7