入力と出力を決める
よい関数は一つの役割を持ち、外側の変数を勝手に書き換えず、結果を戻り値として返します。
平均点を返すR
safe_mean <- function(x) {
mean(x, na.rm = TRUE)
}
result <- safe_mean(c(70, NA, 90))
result実行結果OUTPUT
[1] 80入力を検証する
関数の前提を満たさない値は早い段階で止め、直し方が分かるメッセージを出します。
割合を検証R
discount_price <- function(price, rate) {
if (!is.numeric(price) || length(price) != 1 || is.na(price) || price < 0) {
stop("priceには0以上の数値を1つ指定してください")
}
if (!is.numeric(rate) || length(rate) != 1 || is.na(rate) || rate < 0 || rate > 1) {
stop("rateには0以上1以下の数値を指定してください")
}
floor(price * (1 - rate))
}
discount_price(2000, 0.2)実行結果OUTPUT
[1] 1600全件欠損を区別する
na.rm = TRUEだけでは、すべて欠損の入力でNaNになる場合があります。用途に応じて明示的に扱います。
全件欠損ならNAを返すR
safe_mean <- function(x) {
if (!is.numeric(x)) stop("数値ベクトルを指定してください")
if (length(x) == 0 || all(is.na(x))) return(NA_real_)
mean(x, na.rm = TRUE)
}
safe_mean(c(NA, NA))
safe_mean(c(10, NA, 20))実行結果OUTPUT
[1] NA
[1] 15エラーを処理する
tryCatch()で予想できる失敗へ対応できます。原因を隠さず、記録または利用者向けメッセージへ変換します。
CSV読み込みを試すR
read_sales <- function(path) {
tryCatch(
read.csv(path, fileEncoding = "UTF-8"),
warning = function(w) stop("CSVの形式を確認してください: ", conditionMessage(w)),
error = function(e) stop("CSVを読めませんでした: ", conditionMessage(e))
)
}すべてを無視しない
try(..., silent = TRUE)で失敗を黙らせるだけでは原因を見失います。何を回復できるか決めてから処理します。標準機能で結果を確認する
stopifnot()は条件が偽なら停止します。正常値だけでなく境界値や欠損も試します。
関数を確認R
stopifnot(discount_price(2000, 0.2) == 1600)
stopifnot(discount_price(0, 0.2) == 0)
stopifnot(is.na(safe_mean(c(NA, NA))))
print("すべて成功")実行結果OUTPUT
[1] "すべて成功"testthatでテストを書く
テストが増えたらtestthatで期待値とエラーを読みやすく記述します。
テスト例R
library(testthat)
test_that("値引き価格を計算できる", {
expect_equal(discount_price(2000, 0.2), 1600)
expect_error(discount_price(-1, 0.2), "0以上")
expect_error(discount_price(1000, 1.2), "0以上1以下")
})エラーを調べる
最初のエラーメッセージを読み、入力の型・長さ・欠損を確認します。traceback()は直前のエラーまでの呼び出し、browser()は関数内で値を確認する助けになります。
確認用の出力R
inspect_input <- function(x) {
str(x)
print(length(x))
print(sum(is.na(x)))
invisible(x)
}
inspect_input(c(10, NA, 20))表示の一部OUTPUT
num [1:3] 10 NA 20
[1] 3
[1] 1ミニ課題:合計金額関数
単価と数量の同じ長さの数値ベクトルを受け取り、合計を返す関数を作ってください。長さが違う、負の値がある、欠損がある場合の仕様を決め、テストを書きます。
最低限のテスト
- 通常の複数商品
- 値が1件だけ
- 長さが違う入力
- 負の単価・数量
- 欠損値
