関数の簡単な紹介
最終更新日:2026-10-21 | ページの編集
概要
質問
- 関数とは何ですか?
- なぜ関数の書き方を知っておくべきですか?
- 関数の主な構成要素は何ですか?
目的
- カスタム関数の有用性を理解する
- 関数を書くための基本的な概念を理解する
関数について
Rの関数は、パッケージから提供されるものだと考えるのに慣れているかもしれません。パッケージから専門的な関数を探してインストールし、作業を進めるために使用します。
しかし、自分で関数を書くこともできますし、書くべきだとも言えるでしょう! 関数は、同じ操作を異なる設定で簡単に繰り返すための優れた方法です。 スクリプト内でまったく同じコードをコピー&ペーストし、いくつかの部分(変数や入力など)だけを変更して再び実行したことが何度ありますか? その後でコードにエラーがあることに気づき、修正するときには、そのコードをコピーしたすべての場所で修正することを覚えておかなければなりません。
関数を書くことで、こうした手戻りを減らし、より効率的なワークフローを作ることができます。 バグを見つけたときは、自分で作った関数という1か所を修正するだけで、その後のその関数の呼び出しはすべて修正されたものになります。
さらに、targets
はカスタム関数を多用するため、関数がどのように動作するかについての基本的な理解は、targets
をうまく使うためにとても重要です。
関数を書く
自分で関数を書くことと、Rで他のコードを書くことの間に大きな違いはありません。あなたはこれまでどおりRでコーディングしているのです! ペンギンのデータにあるミリメートルの測定値を、センチメートルに変換したいとしましょう。
R
library(palmerpenguins)
library(tidyverse)
penguins |>
mutate(
bill_length_cm = bill_length_mm / 10,
bill_depth_cm = bill_depth_mm / 10
)
出力
# A tibble: 344 × 10
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
<fct> <fct> <dbl> <dbl> <int> <int>
1 Adelie Torgersen 39.1 18.7 181 3750
2 Adelie Torgersen 39.5 17.4 186 3800
3 Adelie Torgersen 40.3 18 195 3250
4 Adelie Torgersen NA NA NA NA
5 Adelie Torgersen 36.7 19.3 193 3450
6 Adelie Torgersen 39.3 20.6 190 3650
7 Adelie Torgersen 38.9 17.8 181 3625
8 Adelie Torgersen 39.2 19.6 195 4675
9 Adelie Torgersen 34.1 18.1 193 3475
10 Adelie Torgersen 42 20.2 190 4250
# ℹ 334 more rows
# ℹ 4 more variables: sex <fct>, year <int>, bill_length_cm <dbl>,
# bill_depth_cm <dbl>
これは複雑な操作ではありませんが、それでもこの変換を行ってくれる便利なカスタム関数を作りたいかもしれません。
関数を書くには、function() 関数を使用します。
この関数では、関数の入力引数となるものを括弧の中に、そしてそれらの入力引数を使って関数が行う処理を、括弧の後ろの波括弧
{} の中に記述します。
これを代入するオブジェクトの名前が、そのまま関数の名前になります。
R
my_function <- function(argument1, argument2) {
# the things the function will do
}
# call the function
my_function(1, "something")
mm から cm への変換を行う関数は次のようになります:
R
mm2cm <- function(x) {
x / 10
}
このカスタム関数は、任意の数値の入力を10で割って変換します。
試してみましょう:
R
penguins |>
mutate(
bill_length_cm = mm2cm(bill_length_mm),
bill_depth_cm = mm2cm(bill_depth_mm)
)
出力
# A tibble: 344 × 10
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
<fct> <fct> <dbl> <dbl> <int> <int>
1 Adelie Torgersen 39.1 18.7 181 3750
2 Adelie Torgersen 39.5 17.4 186 3800
3 Adelie Torgersen 40.3 18 195 3250
4 Adelie Torgersen NA NA NA NA
5 Adelie Torgersen 36.7 19.3 193 3450
6 Adelie Torgersen 39.3 20.6 190 3650
7 Adelie Torgersen 38.9 17.8 181 3625
8 Adelie Torgersen 39.2 19.6 195 4675
9 Adelie Torgersen 34.1 18.1 193 3475
10 Adelie Torgersen 42 20.2 190 4250
# ℹ 334 more rows
# ℹ 4 more variables: sex <fct>, year <int>, bill_length_cm <dbl>,
# bill_depth_cm <dbl>
おめでとうございます、最初のカスタム関数を作成して使用しました!
既存のコードから関数を作る
すでに手元にあるコードを使って関数を作りたい場合も多いでしょう。
たとえば、あるコードを何度もコピー&ペーストしていて、そのコードが繰り返しになっていることに気づいたとき、関数にするのが適切です。
あるいは、ワークフローを targets
に変換する際に、スクリプトを targets
が呼び出す一連の関数に変更する必要がある場合もあります。
ペンギンのデータをクリーニングするために使ったコードを思い出してください:
R
penguins_data_raw |>
select(
species = Species,
bill_length_mm = `Culmen Length (mm)`,
bill_depth_mm = `Culmen Depth (mm)`
) |>
drop_na()
このコードを関数にするために調整する必要があります。この関数には、クリーニング対象のデータセットという引数が1つ必要です。
次のようになります:
R
clean_penguin_data <- function(penguins_data_raw) {
penguins_data_raw |>
select(
species = Species,
bill_length_mm = `Culmen Length (mm)`,
bill_depth_mm = `Culmen Depth (mm)`
) |>
drop_na()
}
この関数を、_targets.R の library()
でパッケージを読み込む部分の後、末尾のリストの前に追加してください。
RStudioの関数抽出機能
RStudioには、コードの一部から関数を抽出してくれる便利な機能もあります。 関数に少し慣れてくれば、コードを関数にする際に必要な入力を見極めるのに役立つでしょう。
使うには、関数にしたいコードの部分をハイライトします。
今回の場合は、penguins_data_raw から drop_na()
文までのパイプライン全体です。
ハイライトしたら、RStudioの上部バーの「Code」から「Extract
function」を選択します。
Enterキーを押すよう求めるプロンプトが開き、カーソルがあった位置に次のようなコードがスクリプトに挿入されます。
ただし、この関数は引数として必要以上のものを含んでいるため、そのままでは動作しません。
これは、tidyverse が非標準評価を使用しており、select()
の中で引用符なしの列名を書けるためです。
関数抽出機能は、コード内の引用符なし(またはバッククォートで囲まれた)テキストはすべてオブジェクトへの参照だと判断してしまいます。
関数を動作させるには手作業での修正が必要になるため、すでに関数に少し慣れていたほうが便利です。
チャレンジ: 数値ベクトルを受け取り、その平均を10で割った値を返す関数を書いてください。
R
vecmean <- function(x) {
mean(x) / 10
}
ワークフローで関数を使う
カスタムのデータクリーニング関数を定義したので、ワークフローで使ってみましょう。
どのようにすればよいか、わかりますか?
最後の tar_target()
から対応するコードを削除し、新しい関数の呼び出しに置き換える必要があります。
ワークフローを次のように修正してください:
R
library(targets)
library(tidyverse)
library(palmerpenguins)
clean_penguin_data <- function(penguins_data_raw) {
penguins_data_raw |>
select(
species = Species,
bill_length_mm = `Culmen Length (mm)`,
bill_depth_mm = `Culmen Depth (mm)`
) |>
drop_na()
}
list(
tar_target(penguins_csv_file, path_to_file("penguins_raw.csv")),
tar_target(penguins_data_raw, read_csv(
penguins_csv_file, show_col_types = FALSE)),
tar_target(penguins_data, clean_penguin_data(penguins_data_raw))
)
ワークフローが最新の状態であることを確認するため、tar_make()
でもう一度実行しましょう:
出力
Attaching package: ‘palmerpenguins’
The following objects are masked from ‘package:datasets’:
penguins, penguins_raw
R
tar_make()
出力
Attaching package: ‘palmerpenguins’
The following objects are masked from ‘package:datasets’:
penguins, penguins_raw
+ penguins_data dispatched
✔ penguins_data completed [27ms, 1.61 kB]
✔ ended pipeline [198ms, 1 completed, 2 skipped]
targets()
が出力するメッセージについては、すぐ後で詳しく学びます。
関数によってコードの理解が容易になる
末尾のターゲットのリストが、分析の高レベルな要約のように見え始めていることに注目してください。
これはカスタム関数を使うもう一つの利点です:関数を使うことで、各ワークフローステップの詳細を、ワークフロー全体から切り離すことができます。
ワークフロー全体を理解するために、データがどのようにクリーニングされたかの詳細をすべて知る必要はありません。クリーニングのステップがあったことさえわかれば十分です。 一方、データクリーニングの具体的な内容に立ち返って詳しく調べる必要がある場合は、その関数の内部で何が行われているかだけに注目すればよく、ワークフローの残りの部分は無視できます。 これによりコードの理解が容易になり、バグが減り、最終的に時間と労力の節約につながります。
ここでは関数のほんの入り口に触れただけですので、関数について学ぶにはさらに助けが必要になるでしょう。 詳しくは、Carpentries の R Novice レッスンにある、関数についてのエピソードを読むことをお勧めします。
- 同じコードを、わずかな違いで何度も繰り返す場合に、関数は欠かせません
- RStudioの「Extract function」ツールは、コードを関数に変換する作業を始める助けになります
- 関数は
targetsの仕組みに欠かせない要素です