计算熔化数据框中变量的均值,按名称1分组

时间:2014-08-13 08:43:51

标签: r dataframe mean melt split-apply-combine

我在数据框架上使用融合和均值时遇到问题。也许这只是一个初学者问题。

我有一个包含两个条件和3个重复的数据框

set.seed(1)
testdf <- data.frame(name1=letters[1:5],con1_1=floor(runif(5,20,35)),con1_2=floor(runif(5,20,35)),con1_3=floor(runif(5,20,35)),con2_1=floor(runif(5,20,35)),con2_2=floor(runif(5,20,35)),con2_3=floor(runif(5,20,35)))

print(testdf)
  name1 con1_1 con1_2 con1_3 con2_1 con2_2 con2_3
1     a     23     33     23     27     34     25
2     b     25     34     22     30     23     20
3     c     28     29     30     34     29     25
4     d     33     29     25     25     21     33
5     e     23     20     31     31     24     25

现在我融化了数据框以得到这样的东西,我想知道每个条件的平均值......

melt(testdf[1:7],id.vars='name1')
   name1 variable value   mean_con1  mean_con2
1      a   con1_1    23    26.33333   28.66667
2      b   con1_1    25    27.00000   24.33333
3      c   con1_1    28    29.00000   29.33333
4      d   con1_1    33    29.00000   26.33333
5      e   con1_1    23    24.66667   26.66667
6      a   con1_2    33    26.33333   28.66667
7      b   con1_2    34    27.00000   24.33333
8      c   con1_2    29    29.00000   29.33333
9      d   con1_2    29    29.00000   26.33333
10     e   con1_2    20    24.66667   26.66667
11     a   con1_3    23    26.33333   28.66667
...

有没有办法用融化的数据框计算平均值,还是我必须重新创建原始数据框并计算下面的平均值?

testdf$mean_con1 <- apply(testdf[2:4],1,mean)
testdf$mean_con2 <- apply(testdf[5:7],1,mean)

修改

我刚才意识到,我在问题中犯了一个错误。你的答案是正确的,但我实际上正在寻找的只是一栏中的手段。根据变量交替... 这有意义吗?

melt(testdf[1:7],id.vars='name1')
   name1 variable value       mean
1      a   con1_1    23   26.33333
2      b   con1_1    25   27.00000
3      c   con1_1    28   29.00000
4      d   con1_1    33   29.00000
5      e   con1_1    23   24.66667
6      a   con1_2    33   26.33333
7      b   con1_2    34   27.00000
...
16     a   con2_1    27   28.66667
17     b   con2_1    30   24.33333
18     c   con2_1    34   29.33333
19     d   con2_1    25   26.33333
20     e   con2_1    31   26.66667
21     a   con2_2    34   28.66667
22     b   con2_2    23   24.33333
...

好吧,也许我会解释一下我要做的事情。我想用ggplot绘制数据,我想将表示平均值的值和值作为geom_points作为叠加。我希望通过复制来对点进行着色并根据条件对所有内容进行分组...希望有人有个想法......

5 个答案:

答案 0 :(得分:3)

这是一种使用&#34; dplyr&#34;和&#34; tidyr&#34;:

library(dplyr)
library(tidyr)
testdf %>%
  gather(var, val, con1_1:con2_3) %>%
  separate(var, c("var", "time")) %>%
  group_by(name1, var) %>%
  summarise(mVal = mean(val)) %>%
  spread(var, mVal)
# Source: local data frame [5 x 3]
# 
#   name1     con1     con2
# 1     a 26.33333 28.66667
# 2     b 27.00000 24.33333
# 3     c 29.00000 29.33333
# 4     d 29.00000 26.33333
# 5     e 24.66667 26.66667

如果您希望数据保持长格式,请尝试:

testdf %>%
  gather(var, val, con1_1:con2_3) %>%
  separate(var, c("var", "time")) %>%
  group_by(name1, var) %>%
  mutate(mVal = mean(val))

等同于&#34; reshape2&#34;将使用colsplit分割您的&#34;变量&#34;列,并使用dcast获取汇总结果。

library(reshape2)
dfL <- melt(testdf, id.vars = "name1")
dfL <- cbind(dfL, colsplit(dfL$variable, "_", c("var", "time")))
dcast(dfL, name1 ~ var, value.var = "value", mean)
#   name1     con1     con2
# 1     a 26.33333 28.66667
# 2     b 27.00000 24.33333
# 3     c 29.00000 29.33333
# 4     d 29.00000 26.33333
# 5     e 24.66667 26.66667

同样,但长篇大论是:

library(reshape2)
dfL <- melt(testdf, id.vars = "name1")
dfL <- cbind(dfL, colsplit(dfL$variable, "_", c("var", "time")))
dfL$mVal <- with(dfL, ave(value, name1, var))

答案 1 :(得分:1)

使用base函数

 df1 <- reshape(testdf, idvar="name1", varying=2:7, direction="long",sep="_")
 aggregate(df1[,3:4], list(name1=df1[,1]), FUN=mean)
 #  name1     con1     con2
 #1     a 26.33333 28.66667
 #2     b 27.00000 24.33333
 #3     c 29.00000 29.33333
 #4     d 29.00000 26.33333
 #5     e 24.66667 26.66667

或者您可以使用data.table计算重塑后的平均值

 library(data.table)
 setDT(df1)[, lapply(.SD, mean),.SDcols=c("con1", "con2"), by=name1]
 #   name1     con1     con2
 #1:     a 26.33333 28.66667
 #2:     b 27.00000 24.33333
 #3:     c 29.00000 29.33333
 #4:     d 29.00000 26.33333
 #5:     e 24.66667 26.66667

更新

如果您需要长格式

 library(reshape2)
 res <-  within( melt(testdf, id="name1"), {
         variable<- gsub("\\_.*","",variable)
          Mean<- ave(value, name1,variable)})

head(res)
#  name1 variable value     Mean
#1     a     con1    23 26.33333
#2     b     con1    25 27.00000
#3     c     con1    28 29.00000
#4     d     con1    33 29.00000
#5     e     con1    23 24.66667
#6     a     con1    33 26.33333

library(ggplot2)
res$repl <- rep(rep(1:3, each=5),2)
p <- ggplot(res, aes(name1, Mean))
p +
 geom_bar(position="dodge", stat="identity", fill="LightBlue") +
 geom_point(data=res, aes(name1, value, colour=repl))+
 facet_wrap(~variable) +
 theme_bw()

enter image description here

答案 2 :(得分:0)

set.seed(1)
testdf <- data.frame(name1=letters[1:5],con1_1=floor(runif(5,20,35)),con1_2=floor(runif(5,20,35)),con1_3=floor(runif(5,20,35)),con2_1=floor(runif(5,20,35)),con2_2=floor(runif(5,20,35)),con2_3=floor(runif(5,20,35)))
require(reshape2)
melted  <- melt(testdf[1:7],id.vars='name1')
mean(melted$value)

输出:

> mean(melted$value)
[1] 27.16667

答案 3 :(得分:0)

您可以使用融合框架上ddply包中的plyr方法:

require(ddply)
m = melt(testdf[1:7],id.vars='name1')
reshape(ddply(m, .(name1, con=substr(variable, 1,4)), summarize, m = mean(value)), timevar="con", idvar="name1", direction="wide") 

这给了

  name1   m.con1   m.con2
1     a 26.33333 28.66667
3     b 27.00000 24.33333
5     c 29.00000 29.33333
7     d 29.00000 26.33333
9     e 24.66667 26.66667

答案 4 :(得分:0)

然后你可以使用'aggregate'。

set.seed(1)
testdf <- data.frame(name1=letters[1:5],con1_1=floor(runif(5,20,35)),con1_2=floor(runif(5,20,35)),con1_3=floor(runif(5,20,35)),con2_1=floor(runif(5,20,35)),con2_2=floor(runif(5,20,35)),con2_3=floor(runif(5,20,35)))
require(reshape2)
melted  <- melt(testdf[1:7],id.vars='name1')
meanbygroup <- aggregate(melted$value, by=list(melted$variable), FUN=mean)