🍳 Recipesパッケージ完全マスター:日本語での豊富な実例集
recipesパッケージは、機械学習における特徴量エンジニアリングを宣言的かつ再現可能な方法で実現するための革命的なツールです。
日本語での解説例が少ないため、実務でよく使用される様々な前処理パターンを豊富に紹介します。
🏗️ 基本的なRecipe作成パターン
library(tidymodels)
library(tidyverse)
set.seed(123)
housing_data <- tibble(
面積 = rnorm(1000, 70, 20),
築年数 = sample(0:40, 1000, replace = TRUE),
駅距離 = rexp(1000, 0.3),
階数 = sample(1:15, 1000, replace = TRUE),
エリア = sample(c("都心部", "住宅地", "郊外", "駅前"), 1000, replace = TRUE),
建物種別 = sample(c("マンション", "一戸建て", "アパート"), 1000, replace = TRUE),
リフォーム済み = sample(c("済み", "未済"), 1000, replace = TRUE)
) %>%
mutate(
価格 = 3000 + 50 * 面積 - 30 * 築年数 - 200 * 駅距離 +
10 * 階数 + rnorm(1000, 0, 300)
)
basic_recipe <- recipe(価格 ~ ., data = housing_data) %>%
step_normalize(all_numeric_predictors()) %>%
step_dummy(all_nominal_predictors()) %>%
step_zv(all_predictors())
prepped_recipe <- prep(basic_recipe)
processed_data <- bake(prepped_recipe, new_data = NULL)
cat("元データの列数:", ncol(housing_data), "\n")
cat("処理後の列数:", ncol(processed_data), "\n")
cat("追加された変数名:\n")
print(setdiff(names(processed_data), names(housing_data)))
🔧 高度な特徴量エンジニアリング パターン集
polynomial_recipe <- recipe(価格 ~ ., data = housing_data) %>%
step_poly(面積, degree = 3) %>%
step_log(築年数, offset = 1) %>%
step_sqrt(駅距離) %>%
step_count(エリア, 建物種別) %>%
step_lencode_glm(エリア, outcome = vars(価格)) %>%
step_interact(~ 面積:階数) %>%
step_normalize(all_numeric_predictors())
outlier_recipe <- recipe(価格 ~ ., data = housing_data) %>%
step_rm_outliers(面積, 価格, method = "IQR", multiplier = 1.5) %>%
step_impute_median(all_numeric_predictors()) %>%
step_impute_mode(all_nominal_predictors()) %>%
step_range(all_numeric_predictors(), min = 0.05, max = 0.95) %>%
step_normalize(all_numeric_predictors())
timeseries_data <- housing_data %>%
mutate(
売却日 = sample(
seq(as.Date("2020-01-01"), as.Date("2023-12-31"), by = "day"),
1000, replace = TRUE
)
)
datetime_recipe <- recipe(価格 ~ ., data = timeseries_data) %>%
step_date(売却日, features = c("year", "month", "dow")) %>%
step_mutate(四半期 = lubridate::quarter(売却日)) %>%
step_harmonic(売却日_month, frequency = 12, cycle_size = 12) %>%
step_rm(売却日) %>%
step_dummy(all_nominal_predictors()) %>%
step_normalize(all_numeric_predictors())
📝 テキストデータの前処理パターン
text_housing_data <- housing_data %>%
mutate(
物件説明 = sample(c(
"駅近で便利な立地です", "閑静な住宅街にあります", "リフォーム済みで綺麗です",
"日当たり良好で明るいです", "ペット可物件です", "南向きで眺望良好",
"新築同様の美品です", "駐車場完備しています", "商業施設が近くにあります"
), 1000, replace = TRUE)
)
library(textrecipes)
text_recipe <- recipe(価格 ~ ., data = text_housing_data) %>%
step_tokenize(物件説明) %>%
step_tokenfilter(物件説明, min_times = 5) %>%
step_tfidf(物件説明) %>%
step_normalize(all_numeric_predictors()) %>%
step_dummy(all_nominal_predictors())
advanced_text_recipe <- recipe(価格 ~ ., data = text_housing_data) %>%
step_mutate(
説明文字数 = nchar(物件説明),
説明単語数 = stringr::str_count(物件説明, "\\S+")
) %>%
step_mutate(
駅近フラグ = ifelse(stringr::str_detect(物件説明, "駅近"), 1, 0),
リフォームフラグ = ifelse(stringr::str_detect(物件説明, "リフォーム"), 1, 0),
日当たりフラグ = ifelse(stringr::str_detect(物件説明, "日当たり"), 1, 0)
) %>%
step_rm(物件説明) %>%
step_normalize(all_numeric_predictors()) %>%
step_dummy(all_nominal_predictors())
📐 次元削減と主成分分析
high_dim_data <- housing_data %>%
mutate(
学校距離 = rexp(1000, 0.5),
病院距離 = rexp(1000, 0.3),
商店街距離 = rexp(1000, 0.4),
公園距離 = rexp(1000, 0.6),
コンビニ距離 = rexp(1000, 0.8),
バルコニー面積 = rnorm(1000, 8, 3),
収納面積 = rnorm(1000, 5, 2),
天井高 = rnorm(1000, 2.4, 0.2),
部屋数 = sample(1:5, 1000, replace = TRUE)
)
pca_recipe <- recipe(価格 ~ ., data = high_dim_data) %>%
step_dummy(all_nominal_predictors()) %>%
step_zv(all_predictors()) %>%
step_normalize(all_numeric_predictors()) %>%
step_pca(all_numeric_predictors(), threshold = 0.9) %>%
step_corr(all_numeric_predictors(), threshold = 0.8)
ica_recipe <- recipe(価格 ~ ., data = high_dim_data) %>%
step_dummy(all_nominal_predictors()) %>%
step_zv(all_predictors()) %>%
step_normalize(all_numeric_predictors()) %>%
step_ica(all_numeric_predictors(), num_comp = 5)
umap_recipe <- recipe(価格 ~ ., data = high_dim_data) %>%
step_dummy(all_nominal_predictors()) %>%
step_normalize(all_numeric_predictors()) %>%
step_umap(all_numeric_predictors(), num_comp = 2)
🎯 実務で役立つ特殊な前処理パターン
library(themis)
imbalanced_data <- housing_data %>%
mutate(
高額物件 = ifelse(価格 > quantile(価格, 0.8), "Yes", "No") %>% as.factor()
) %>%
select(-価格)
resampling_recipe <- recipe(高額物件 ~ ., data = imbalanced_data) %>%
step_smote(高額物件) %>%
step_normalize(all_numeric_predictors()) %>%
step_dummy(all_nominal_predictors())
価格帯分類 <- function(価格) {
case_when(
価格 < 2000 ~ "低価格帯",
価格 < 4000 ~ "中価格帯",
価格 < 6000 ~ "高価格帯",
TRUE ~ "超高級"
)
}
custom_recipe <- recipe(価格 ~ ., data = housing_data) %>%
step_mutate(
面積築年数比 = 面積 / (pmax(築年数, 1)),
駅近度 = 1 / (1 + 駅距離),
新築フラグ = ifelse(築年数 <= 3, 1, 0),
大型物件フラグ = ifelse(面積 >= 100, 1, 0)
) %>%
step_YeoJohnson(all_numeric_predictors()) %>%
step_normalize(all_numeric_predictors()) %>%
step_dummy(all_nominal_predictors())
comprehensive_recipe <- recipe(価格 ~ ., data = housing_data) %>%
step_filter(面積 > 0, 築年数 >= 0) %>%
step_impute_knn(all_numeric_predictors(), neighbors = 5) %>%
step_mutate(log_面積 = log(面積 + 1)) %>%
step_interact(~ 面積:エリア) %>%
step_novel(all_nominal_predictors()) %>%
step_other(all_nominal_predictors(), threshold = 0.01) %>%
step_dummy(all_nominal_predictors()) %>%
step_zv(all_predictors()) %>%
step_normalize(all_numeric_predictors()) %>%
step_corr(all_numeric_predictors(), threshold = 0.9)
cat("=== Recipe処理結果の比較 ===\n")
recipes_list <- list(
基本処理 = basic_recipe,
多項式処理 = polynomial_recipe,
外れ値処理 = outlier_recipe,
PCA処理 = pca_recipe,
包括処理 = comprehensive_recipe
)
purrr::imap(recipes_list, function(recipe, name) {
prepped <- prep(recipe)
processed <- bake(prepped, new_data = NULL)
cat(sprintf("%s: %d列 → %d列\n", name, ncol(housing_data), ncol(processed)))
})