Menu

R で列を追加・変換する(mutate と base R)

データフレームの列を追加・変換・削除する方法: df$new <- ...、条件付き列のための ifelse()、transform()、そして case_when() を伴う dplyr の mutate()。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

列の追加: 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) がそれを除いたコピーを返します。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める