昨日は、あまり意味がない関数だったんで、ちょっと工夫してみる。
- vector からNA を除き、上下5% を除外したmean とsd を計算する関数
> trim_mn <- function(x,alpha=.05){ # alpha=.05 がデフォルト値 + x <- sort(x) + x[1:ceiling(length(x)*alpha)] <- NA + x <- rev(x) + x[1:ceiling(length(x)*alpha)] <- NA + c("mean"=mean(x,na.rm=TRUE),"sd"=sd(x,na.rm=TRUE)) + } > x <- sample(100,50) > x[sample(50,10)] <- NA > trim_mn(x) mean sd 51.80556 26.82943 > trim_mn(x,alpha=.1) # 上下10% にしたい場合 mean sd 51.68750 23.66083
- 更に、「NA の除外する」か「NAに最小値の補完する」を選ばせる
> trim_mn2 <- function(x,alpha=.05,inpute=FALSE){ + if(inpute) x[is.na(x)] <- min(x,na.rm=TRUE) + trim_mn(x,alpha=alpha) # 先に定義したtrim_mn を持ってきている + } > trim_mn2(x,inpute=TRUE) mean sd 40.40909 30.64297 > trim_mn2(x) # inpute=FALSE なのでtrim_mn(x) と同じ mean sd 51.80556 26.82943
てなこともできる。
で、function関数で作ったオブジェクトは関数として使えるので、apply関数の第3引数になる
- function関数をapply関数にぶち込む
> x <- matrix(x,ncol=5) > apply(x,2,trim_mn2,inpute=TRUE) [,1] [,2] [,3] [,4] [,5] mean 30.00000 46.37500 35.25000 66.5000 30.50000 sd 26.29503 19.11572 33.39696 21.9545 25.59576
同じ処理をfor で処理すると、こんなコードになるかも
> y <- NULL > for(i in 1:ncol(x)){ + z <- sort(x[,i]) + z[1:ceiling(length(z)*.05)] <- NA + z <- rev(z) + z[1:ceiling(length(z)*.05)] <- NA + y <- cbind(y,c("mean"=mean(z,na.rm=TRUE),"sd"=sd(z,na.rm=TRUE))) + }
- function関数の定義をone-linerで書けるなら、applyの第3引数に直接、書き込んでも可
# apply(x,2,mn_sd2,na.rm=TRUE)をone-linerで記述する > apply(x,2,function(x) c("mean"=mean(x,na.rm=TRUE),"sd"=sd(x,na.rm=TRUE))) [,1] [,2] [,3] [,4] [,5] mean 38.87500 51.33333 47.37500 74.25000 46.00000 sd 27.07892 23.25941 37.38578 20.97447 33.21646