16

1つのtapplyまたはaggregateステートメントに2つの関数を含めることは可能ですか?

以下では、2つのtapplyステートメントと2つのaggregateステートメントを使用します。1つは平均用、もう1つは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

いつでも2つの別々のステートメントを実行して、出力をマージできます。もう少し便利な解決策があるのではないかと思っていました。

私はここに投稿された以下の答えを見つけました: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ます。パッケージのソリューションは上のリンクに投稿されました。上記の出力に正しい行と列の見出しを追加できれば、それは完璧です。

4

4 に答える 4

18

しかし、これらは持っている必要があります:

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.

遵守すべき原則は、関数が「1つのもの」を返すようにすることです。これは、ベクトルまたはリストのいずれかですが、2つの関数呼び出しを連続して呼び出すことはできません。

于 2013-03-05T03:09:32.907 に答える
10

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

NAsdの値がないように、わずかに異なるデータセットを使用しました

于 2013-03-05T03:26:53.003 に答える
7

共有の精神で、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
于 2013-03-05T18:26:29.947 に答える
5

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のおかげです。

于 2013-03-05T04:10:44.890 に答える