Вычислить средние значения переменных в расплавленном фрейме данных, сгруппированные по имени1

У меня проблема с использованием плавления и среднего значения во фрейме данных. Возможно, это просто проблема новичка.

У меня есть фрейм данных с двумя условиями и 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 в качестве наложения. Я хочу раскрасить точки по повторениям и сгруппировать все по условию... Надеюсь, у кого-то есть идея...


person drmariod    schedule 13.08.2014    source источник
comment
Пожалуйста, проверьте мое обновленное решение   -  person akrun    schedule 13.08.2014
comment
Добавление вашей проблемы с графиком значительно меняет вопрос и на самом деле не является хорошим способом задавать вопросы по SO. Лучше всего изолировать эти разные проблемы как разные вопросы.   -  person A5C1D2H2I1M1N2O1R2T1    schedule 13.08.2014
comment
Заголовок «Вычислить средние значения переменных в расплавленном фрейме данных, сгруппированных по имени1» говорит нам гораздо больше, чем «проблемы с использованием плавления и среднего».   -  person smci    schedule 06.11.2016
comment
@smci Спасибо, что указали на это. Иногда трудно подобрать хорошее название для задачи :-)   -  person drmariod    schedule 07.11.2016


Ответы (5)


используя 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()

введите здесь описание изображения

person akrun    schedule 13.08.2014

Вот подход с использованием «dplyr» и «tidyr»:

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))

Эквивалентом «reshape2» будет использование colsplit для разделения столбца «переменная» и использование 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))
person A5C1D2H2I1M1N2O1R2T1    schedule 13.08.2014
comment
Мне нравится версия reshape2! Вместе с cbind и расплавленным фреймом данных это дает результат, который я искал, спасибо - person drmariod; 13.08.2014
comment
Я только что понял, что я сделал что-то не так в своем первоначальном вопросе. Я изменил, может у вас есть идея, как решить проблему - person drmariod; 13.08.2014

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
person tagoma    schedule 13.08.2014
comment
это дает общее среднее значение, но мне нужно среднее значение трех повторов для каждого условия... - person drmariod; 13.08.2014

Тогда вы можете использовать «агрегат».

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)
person tagoma    schedule 13.08.2014

Вы можете использовать метод 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
person martin    schedule 13.08.2014