Несколько функций в одном заявлении или агрегированном заявлении
Можно ли включить две функции в одно выражение или обобщенную инструкцию?
Ниже я использую два оператора tapply и два агрегатных оператора: один для среднего и один для SD.
Я бы предпочел объединить утверждения.
my.Data = read.table(text = "
animal age sex weight
1 adult female 100
2 young male 75
3 adult male 90
4 adult female 95
5 young female 80
", sep = "", header = TRUE)
with(my.Data, tapply(weight, list(age, sex), function(x) {mean(x)}))
with(my.Data, tapply(weight, list(age, sex), function(x) {sd(x) }))
with(my.Data, aggregate(weight ~ age + sex, FUN = mean)
with(my.Data, aggregate(weight ~ age + sex, FUN = sd)
# this does not work:
with(my.Data, tapply(weight, list(age, sex), function(x) {mean(x) ; sd(x)}))
# I would also prefer that the output be formatted something similar to that
# show below. `aggregate` formats the output perfectly. I just cannot figure
# out how to implement two functions in one statement.
age sex mean sd
adult female 97.5 3.535534
adult male 90 NA
young female 80.0 NA
young male 75 NA
Я всегда могу запускать два отдельных оператора и объединять выходные данные. Я просто надеялся, что может быть
немного более удобное решение.
Я нашел приведенный ниже ответ: Применить несколько функций к столбцу, используя tapply
f <- function(x) c(mean(x), sd(x))
do.call( rbind, with(my.Data, tapply(weight, list(age, sex), f)) )
Однако ни строки, ни столбцы не помечены.
[,1] [,2]
[1,] 97.5 3.535534
[2,] 80.0 NA
[3,] 90.0 NA
[4,] 75.0 NA
Я предпочел бы решение в базе R. Решение из пакета plyr
было опубликовано по ссылке выше. Если я могу добавить правильные заголовки строк и столбцов к указанному выше выводу, это будет идеально.
Ответы
Ответ 1
Но они должны иметь:
with(my.Data, aggregate(weight, list(age, sex), function(x) { c(MEAN=mean(x), SD=sd(x) )}))
with(my.Data, tapply(weight, list(age, sex), function(x) { c(mean(x) , sd(x) )} ))
# Not a nice structure but the results are in there
with(my.Data, aggregate(weight ~ age + sex, FUN = function(x) c( SD = sd(x), MN= mean(x) ) ) )
age sex weight.SD weight.MN
1 adult female 3.535534 97.500000
2 young female NA 80.000000
3 adult male NA 90.000000
4 young male NA 75.
Принцип, которым нужно придерживаться, состоит в том, чтобы вернуть вашу функцию "одна вещь", которая может быть либо вектором, либо списком, но не может быть последовательным вызовом двух вызовов функций.
Ответ 2
Если вы хотите использовать data.table, он имеет with
и by
, встроенные в него:
library(data.table)
myDT <- data.table(my.Data, key="animal")
myDT[, c("mean", "sd") := list(mean(weight), sd(weight)), by=list(age, sex)]
myDT[, list(mean_Aggr=sum(mean(weight)), sd_Aggr=sum(sd(weight))), by=list(age, sex)]
age sex mean_Aggr sd_Aggr
1: adult female 96.0 3.6055513
2: young male 76.5 2.1213203
3: adult male 91.0 1.4142136
4: young female 84.5 0.7071068
Я использовал немного другой набор данных, чтобы не иметь значений NA
для sd
Ответ 3
В духе совместного использования, если вы знакомы с SQL, вы также можете рассмотреть пакет sqldf. (Акцент добавлен, потому что вам нужно знать, например, что mean
- avg
, чтобы получить желаемые результаты.)
sqldf("select age, sex,
avg(weight) `Wt.Mean`,
stdev(weight) `Wt.SD`
from `my.Data`
group by age, sex")
age sex Wt.Mean Wt.SD
1 adult female 97.5 3.535534
2 adult male 90.0 0.000000
3 young female 80.0 0.000000
4 young male 75.0 0.000000
Ответ 4
Reshape позволяет вам передавать 2 функции; reshape2 - нет.
library(reshape)
my.Data = read.table(text = "
animal age sex weight
1 adult female 100
2 young male 75
3 adult male 90
4 adult female 95
5 young female 80
", sep = "", header = TRUE)
my.Data[,1]<- NULL
(a1<- melt(my.Data, id=c("age", "sex"), measured=c("weight")))
(cast(a1, age + sex ~ variable, c(mean, sd), fill=NA))
# age sex weight_mean weight_sd
# 1 adult female 97.5 3.535534
# 2 adult male 90.0 NA
# 3 young female 80.0 NA
# 4 young male 75.0 NA
Я обязан этим @Ramnath, который отметил этот только вчера.