列の追加: df$new <- value
base R で列を追加するには、まだ存在しない名前に代入します。値は通常、既存の列から計算します。
2 つのことが起きました。orders$total は完全なベクトルを受け取りました — R の算術はベクトル化されているので、price * qty は全行について一度に計算されます。orders$currency は単一の値を受け取り、R がそれを 4 行すべてに 再利用(リサイクル) しました。それ以外の長さはエラーになります(replacement has 3 rows, data has 4)。これは R が列のずれからあなたを守っているのです。
これが動くのは、データフレームが長さの等しい列のリストだからです。新しい名前付き要素への代入がリストを伸ばします。データフレームのドキュメント がそのモデルを解説しています。
条件付きの列: ifelse()
値が条件に依存する列には ifelse() — if の ベクトル化された いとこ — が必要です。条件のベクトル全体を受け取り、行ごとに値を返します。
なぜ素の if ではだめなのでしょうか。if はちょうど 1 つの TRUE/FALSE を評価するからです — 列を渡すとエラーになります(the condition has length > 1)。ifelse(test, yes, no) は各要素を判定し、行ごとに選びます。結果が 3 つ以上ある場合は入れ子にできます。
2 段の入れ子までなら問題ありませんが、3 段以上になるとピラミッドになります — dplyr の case_when()(後述)はまさにその仕事のために作られました。単一の値を扱う if/else そのものは if-else のドキュメント で扱っています。
一度に複数の列: transform()
base R の transform() は、裸の列名を使って 1 回の呼び出しで複数の列を追加します。
transform() は 新しい データフレームを返す点に注意してください — 結果を代入し直す必要があります。一方 df$new <- ... はその場で変更します。制約が 1 つあります。1 回の transform() 呼び出し内の式どうしは互いを参照できないので、discount = ifelse(total > 50, ...) はそこでは失敗します(total はまだ存在しません)。2 段階に分けるか、それを許す mutate() を使いましょう。
変更と作成
同じ代入構文が既存の列を上書きします。その列がすでに存在していたかどうかだけが違いです。
ここは立ち止まる価値があります。列を上書きしても R は何の警告も出しません。df$prise <- round(df$price, 2) のような打ち間違いは、古い列を直す代わりに黙って新しい列を 作成 します。変換の後は、フレームを print() か str() して、意図したものを変えたか確認しましょう。
列の削除
削除するには NULL を代入します。
儀式なしで列が消えます。複数を削除するには、NULL を繰り返すより df[, c("a", "b")](残すものを列挙する)の方がたいてい明快です。
dplyr のやり方: mutate()
上記すべてに対する dplyr の動詞が mutate() です。以下のスニペットは静的です(サンドボックスは base R しか実行しません)が、同じ操作はこのように書けます。
library(dplyr)
orders |>
mutate(
total = price * qty,
big = total > 50 # can use total, defined one line up
)
base R に対する利点が 2 つあります。第 1 に、同じ mutate() の中で定義した列どうしが、順番に互いを参照 できます — transform() が拒むことです。第 2 に、条件用のヘルパーが入れ子の ifelse() より優れています。
students |>
mutate(
grade = if_else(score >= 60, "pass", "fail"),
band = case_when(
score >= 85 ~ "high",
score >= 60 ~ "mid",
.default = "low"
)
)
if_else() はより厳格な ifelse() です(両方の分岐が同じ型でなければならず、実際のバグを捕まえます)。case_when() は上から下へ判定される condition ~ value の対の平坦なリストとして読め、.default がフォールバックになります — ifelse() のピラミッドの読みやすい代替です。すべての dplyr の動詞と同様、mutate() は新しいデータフレームを返します。他の動詞とどう連鎖するかは dplyr 入門 を参照してください。
この記事のまとめ
df$new <- expressionは列を追加します。式は全行に対して一度に実行されます。ifelse(test, yes, no)は条件付きの列を作ります。素のifにはできません。transform()は 1 回の呼び出しで複数の列を追加できますが、互いを参照できません。mutate()はできます。- 同じ代入は黙って上書きします — 変換の後は綴りを確認しましょう。
df$col <- NULLは列を削除します。case_when()は入れ子のifelse()のピラミッドを置き換えます。
次は 列名の変更 — names()、堅牢な base の定型句、そして dplyr の rename() です。
よくある質問
R でデータフレームに新しい列を追加するにはどうすればよいですか?
まだ存在しない列名に代入します: df$total <- df$price * df$qty。R はその場で列を作成します。値は単一の値(全行に再利用されます)でも、他の列から計算したベクトルでも構いません。ただし長さが行数と一致する必要があります。
R で条件付きの列を作るにはどうすればよいですか?
ベクトル化された ifelse() を使います: df$grade <- ifelse(df$score >= 60, "pass", "fail") は全行を一度に判定します。素の if は使わないでください — 単一の条件を扱うもので、列は扱えません。3 つ以上の結果が必要なら ifelse() を入れ子にするか、dplyr の case_when() を使います。
R の mutate() は何をしますか?
mutate() は列を追加・変換するための dplyr の動詞です: df |> mutate(total = price * qty) は新しい列を持つデータフレームのコピーを返します。1 回の呼び出しで複数の列を定義でき、後の列は同じ mutate の中で先に定義した列を使えます。
R でデータフレームから列を削除するにはどうすればよいですか?
NULL を代入します: df$notes <- NULL はその場で列を削除します。dplyr では select(-notes) がそれを除いたコピーを返します。