日々のつれづれ

不惑をむかえ戸惑いを隠せない男性の独り言

function関数の使い方、その2

昨日は、あまり意味がない関数だったんで、ちょっと工夫してみる。

  • 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