No.21606 関数のスリム化  【コロン】 2015/04/16(Thu) 17:42

いつもお世話になっております。

練習としてBMIの判定関数を作りましたが,美しくないと勝手に感じております。
return(data.frame...をなんかいも使っていますので....。
もしスリム化できるのであればご教授ください。
それからdata.frameにした時の左端の1が気になります.....。

myBMI <- function(weight, height){
BMI <- weight/(height*height)
if (BMI >= 40) return(data.frame(BMI = BMI, 肥満度指数 = "肥満度4"))
else if (35.0 <= BMI) return(data.frame(BMI = BMI, 肥満度指数 = "肥満度3"))
else if (30.0 <= BMI) return(data.frame(BMI = BMI, 肥満度指数 = "肥満度2"))
else if (25.0 <= BMI) return(data.frame(BMI = BMI, 肥満度指数 = "肥満度1"))
else if (18.5 <= BMI) return(data.frame(BMI = BMI, 肥満度指数 = "標準"))
else return(data.frame(BMI = BMI, 肥満度指数 = "低体重"))
}

No.21607 Re: 関数のスリム化  【青木繁伸】 2015/04/16(Thu) 18:30

こりに凝った関数仕様にしてみました。必要なところだけをつまんでください。
myBMI <- function(weight, height){
BMI <- weight/(height*height)
i <- if (40.0 <= BMI) 1
else if (35.0 <= BMI) 2
else if (30.0 <= BMI) 3
else if (25.0 <= BMI) 4
else if (18.5 <= BMI) 5
else 6
return(structure(c(
BMI=BMI, 肥満度指数=c("肥満度4", "肥満度3", "肥満度2", "肥満度1", "標準", "低体重")[i]),
class="myBMI"))
}
print.myBMI <- function(x, digits=5) {
y <- data.frame(as.numeric(x[1]), x[2])
colnames(y)=names(x)
print(y, digits=digits, row.names=FALSE)
}

a <- myBMI(65, 1.63)

a # これ以下の3つは同じ働き
print(a)
print.myBMI(a)

str(a) # myBMI クラスの構成
print.default(a) # myBMI クラスの構成
区分分けは cut を使うとよい。
myBMI2 <- function(weight, height) {
BMI <- weight/(height^2)
index=cut(BMI, breaks=c(0, 18.5, 25, 30, 35, 40, Inf), right=FALSE,
labels=c("低体重", "標準", "肥満度1", "肥満度2", "肥満度3", "肥満度4" ))
return(data.frame(BMI=BMI, 肥満度指数=index))
}
a = myBMI2(65, 1.65)
print(a, row.names=FALSE) # 行名を出力しない

No.21608 Re: 関数のスリム化  【コロン】 2015/04/17(Fri) 08:21

青木先生

早速のご指導ありがとうございます。やはり先生の書かれたものは「美しい」と思いました。

新たに追加してくださいましたcutを使う方はすぐに理解することができました。

お忙しい中,本当にありがとうございました。

No.21609 Re: 関数のスリム化  【青木繁伸】 2015/04/17(Fri) 21:01

よいプログラムかどうかは別として,プログラムを書くときには,

「同じようなことが何回も書かれていないか」というのは考慮の対象になるでしょうね。
それを避けるにはどのようにすればよいかということがメインテーマになるわけです。

● 「統計学関連なんでもあり」の過去ログ--- 047 の目次へジャンプ
● 「統計学関連なんでもあり」の目次へジャンプ
● 直前のページへ戻る