R言語のデータフレームで文字列の列を複数の列に分割する方法について解説します。このような方法はいくつかあり、R言語に標準で搭載されている機能を使用した方法もありますが、ここではtidyverseパッケージに含まれているtidyrパッケージのseparate()を使用した方法についてお伝えします。separate()を使用する利点は、パイプ演算子と親和性が高くR言語に標準で搭載されている機能を使用する方法よりも可読性が高いコードが書けることが挙げられます。
separate()はseparate_wider_position()とseparate_wider_delim()、separate_wider_regex()に取って代わられました。これは、関数の使用がより明確になり、APIがより洗練され、問題の処理が改善されたためです。関数separate()は消えず、重大なバグ修正のみを受け取ります。しかしながら、tidyrのversion 1.3.1において、separate_wider_position()とseparate_wider_delim()、separate_wider_regex()は実験的な位置付けとなっています。

separate()の概要

separate()は、正規表現または数値位置を使用して文字列を複数の列に分割するための関数です。

separate()の使い方

tidyr::separate()の使い方は次になります。


separate(
  data,
  col,
  into,
  sep = "[^[:alnum:]]+",
  remove = TRUE,
  convert = FALSE,
  extra = "warn",
  fill = "warn",
  ...
)

separate()の引数の意味

data

データフレームを指定します。

col

tidy-selectを指定できます。展開する列を指定します。

into

文字ベクトルとして作成する新しい列名を指定します。
出力で変数を省略するにはNAを使用します。

sep = “[^[:alnum:]]+”

列間の区切り文字を指定します。
文字の場合、sepは正規表現として解釈されます。デフォルト値は、英数字以外の値の任意のシーケンスに一致する正規表現です。数値の場合、sepは分割する文字位置として解釈されます。正の値は文字列の左端の1から始まり、負の値は文字列の右端の-1から始まります。sepの長さはintoより1短くする必要があります。

remove = TRUE

TRUEの場合、出力データフレームから入力列を削除します。

convert = FALSE

TRUEの場合、新しい列に対してas.is = TRUEでtype.convert()を実行します。これは、コンポーネント列が整数、数値、または論理である場合に便利です。これにより、文字列”NA”がNA に変換されます。

extra = “warn”

sepが文字ベクトルの場合、これはピースが多すぎる場合に何が起こるかを制御します。有効なオプションは3つあります。

  • warn(デフォルト): 警告を発し、余分な値を削除します
  • drop: 警告なしで余分な値を削除します
  • merge: 最大で length(into) 回だけ分割します
fill = “warn”

sepが文字ベクトルの場合、ピースが足りないときに何が起こるかを制御します。有効なオプションは3つあります。

  • warn(デフォルト): 警告を発し、右から埋めます
  • right: 右側の欠損値で埋めます
  • left: 左側の欠損値で埋めます

関数に渡される追加の引数です。

separate_wider_delim()の概要

separate_wider_delim()は、区切り文字を使用して文字列を複数の列に分割するための関数です。

separate_wider_delim()の使い方

tidyr::separate_wider_delim()の使い方は次になります。


separate_wider_delim(
  data,
  cols,
  delim,
  ...,
  names = NULL,
  names_sep = NULL,
  names_repair = "check_unique",
  too_few = c("error", "debug", "align_start", "align_end"),
  too_many = c("error", "debug", "drop", "merge"),
  cols_remove = TRUE
)

separate_wider_delim()の引数の意味

data

データフレームを指定します。

cols

tidy-selectを指定できます。展開する列を指定します。

delim

値間の区切り文字を指定する文字列を指定します。
デフォルトでは、固定文字列として解釈されます。他の方法で分割するには、stringr::regex()などを使用します。

これらのドットは将来の拡張用であり、空である必要があります。

names = NULL

出力列名の文字ベクトルを指定します。
出力に表示したくないコンポーネントがある場合はNAを使用します。NA以外の要素の数によって、結果の新しい列の数が決まります。

names_sep = NULL

指定されている場合、出力名は入力列名、区切り文字、新しい列名で構成されます。colsが複数の列を選択する場合に必須です。
namesの代わりに指定できます。その場合、名前はソース列名およびnames_sep、数値サフィックスから生成されます。

names_repair = “check_unique”

出力データフレームに有効な名前があるかどうかを確認するために使用されます。次のオプションのいずれかである必要があります。

  • minimal: 基本的な存在以外は名前の修復やチェックは行いません
  • unique: 名前が一意で空でないことを確認します
  • check_unique(デフォルト): 名前の修復は行いませんが、一意であることを確認します
  • universal: 名前を一意で構文的にします
  • 関数: カスタムの名前修復を適用します
  • tidyr_legacy: tidyr 0.8 の名前修復を使用します
  • formula: purrrスタイルの匿名関数(rlang::as_function()を参照)

これらの用語と、それらを強制するために使用される戦略の詳細については、vctrs::vec_as_names()を参照してください。

too_few = c(“error”, “debug”, “align_start”, “align_end”)

値が分割される部分が少なすぎる場合はどうするかを指定します。

  • error(デフォルト): エラーをスローします
  • debug: 根本的な問題を見つけて解決するのに役立つ追加の列を出力に追加します。このオプションは、問題のデバッグと対処を支援するためのものであり、通常は最終コードに残すべきではありません
  • align_start: 短い一致の開始を揃え、末尾にNAを追加して正しい長さにパディングします
  • align_end: 短い一致の末尾を揃え、先頭にNAを追加して正しい長さにパディングします
too_many = c(“error”, “debug”, “drop”, “merge”)

値が分割されすぎた場合にどうするかを指定します。

  • error(デフォルト): エラーをスローします
  • debug: 根本的な問題を見つけて解決するのに役立つ追加の列を出力に追加します
  • drop: 余分な部分を暗黙的に削除します
  • merge: 追加の部分を結合します
cols_remove = TRUE

入力列を出力から削除する必要があるかどうかを指定します。
too_fewまたはtoo_manyが「debug」に設定されている場合は常にFALSEです。

separate_wider_position()の概要

separate_wider_position()は、固定幅で分割するための関数です。

separate_wider_position()の使い方

separate_wider_position()の使い方は次になります。


separate_wider_position(
  data,
  cols,
  widths,
  ...,
  names_sep = NULL,
  names_repair = "check_unique",
  too_few = c("error", "debug", "align_start"),
  too_many = c("error", "debug", "drop"),
  cols_remove = TRUE
)

separate_wider_position()の引数の意味

data

データフレームを指定します。

cols

tidy-selectを指定できます。展開する列を指定します。

widths

名前が列名になり、値が列の幅を指定する名前付き数値ベクトルを指定します。
名前のないコンポーネントは一致しますが、出力には含まれません。

これらのドットは将来の拡張用であり、空である必要があります。

names_sep = NULL

指定されている場合、出力名は入力列名、区切り文字、新しい列名で構成されます。colsが複数の列を選択する場合に必須です。
namesの代わりに指定できます。その場合、名前はソース列名およびnames_sep、数値サフィックスから生成されます。

names_repair = “check_unique”

出力データフレームに有効な名前があるかどうかを確認するために使用されます。次のオプションのいずれかである必要があります。

  • minimal: 基本的な存在以外は名前の修復やチェックは行いません
  • unique: 名前が一意で空でないことを確認します
  • check_unique(デフォルト): 名前の修復は行いませんが、一意であることを確認します
  • universal: 名前を一意で構文的にします
  • 関数: カスタムの名前修復を適用します
  • tidyr_legacy: tidyr 0.8 の名前修復を使用します
  • formula: purrrスタイルの匿名関数(rlang::as_function()を参照)

これらの用語と、それらを強制するために使用される戦略の詳細については、vctrs::vec_as_names()を参照してください。

too_few = c(“error”, “debug”, “align_start”)

値が分割される部分が少なすぎる場合はどうするかを指定します。

  • error(デフォルト): エラーをスローします
  • debug: 根本的な問題を見つけて解決するのに役立つ追加の列を出力に追加します。このオプションは、問題のデバッグと対処を支援するためのものであり、通常は最終コードに残すべきではありません
  • align_start: 短い一致の開始を揃え、末尾にNAを追加して正しい長さにパディングします
too_many = c(“error”, “debug”, “drop”)

値が分割されすぎた場合にどうするかを指定します。

  • error(デフォルト): エラーをスローします
  • debug: 根本的な問題を見つけて解決するのに役立つ追加の列を出力に追加します
  • drop: 余分な部分を暗黙的に削除します
cols_remove = TRUE

入力列を出力から削除する必要があるかどうかを指定します。
too_fewまたはtoo_manyが「debug」に設定されている場合は常にFALSEです。

separate_wider_regex()の概要

separate_wider_regex()は、正規表現で分割するための関数です。

separate_wider_regex()の使い方

separate_wider_regex()の使い方は次になります。


separate_wider_regex(
  data,
  cols,
  patterns,
  ...,
  names_sep = NULL,
  names_repair = "check_unique",
  too_few = c("error", "debug", "align_start"),
  cols_remove = TRUE
)

separate_wider_regex()の引数の意味

data

データフレームを指定します。

cols

tidy-selectを指定できます。展開する列を指定します。

patterns

名前が列名になり、値がベクトルの内容に一致する正規表現である名前付き文字ベクトルを指定します。
名前のないコンポーネントは一致しますが、出力には含まれません。

これらのドットは将来の拡張用であり、空である必要があります。

names_sep = NULL

指定されている場合、出力名は入力列名、区切り文字、新しい列名で構成されます。colsが複数の列を選択する場合に必須です。
namesの代わりに指定できます。その場合、名前はソース列名およびnames_sep、数値サフィックスから生成されます。

names_repair = “check_unique”

出力データフレームに有効な名前があるかどうかを確認するために使用されます。次のオプションのいずれかである必要があります。

  • minimal: 基本的な存在以外は名前の修復やチェックは行いません
  • unique: 名前が一意で空でないことを確認します
  • check_unique(デフォルト): 名前の修復は行いませんが、一意であることを確認します
  • universal: 名前を一意で構文的にします
  • 関数: カスタムの名前修復を適用します
  • tidyr_legacy: tidyr 0.8 の名前修復を使用します
  • formula: purrrスタイルの匿名関数(rlang::as_function()を参照)

これらの用語と、それらを強制するために使用される戦略の詳細については、vctrs::vec_as_names()を参照してください。

too_few = c(“error”, “debug”, “align_start”)

値が分割される部分が少なすぎる場合はどうするかを指定します。

  • error(デフォルト): エラーをスローします
  • debug: 根本的な問題を見つけて解決するのに役立つ追加の列を出力に追加します。このオプションは、問題のデバッグと対処を支援するためのものであり、通常は最終コードに残すべきではありません
  • align_start: 短い一致の開始を揃え、末尾にNAを追加して正しい長さにパディングします
cols_remove = TRUE

入力列を出力から削除する必要があるかどうかを指定します。
too_fewまたはtoo_manyが「debug」に設定されている場合は常にFALSEです。

準備

あらかじめ、tidyverseパッケージを読み込んでおきます。


library(tidyverse)

解説のために、次のサンプルデータフレームを準備します。


df <- data.frame(
    x = c("2001-01-01", "2002-02-02", "2003-03-03")
  )

df

           x
1 2001-01-01
2 2002-02-02
3 2003-03-03

separate()で展開

サンプルデータフレームで、列xを「-」で展開するには次のようにします。


df |>
  separate(x, c("year", "month", "day"), sep = "-")

  year month day
1 2001    01  01
2 2002    02  02
3 2003    03  03

separate_wider_delim()で展開

サンプルデータフレームで、列xを「-」で展開するには次のようにします。


df |>
  separate_wider_delim(x, "-", names = c("year", "month", "day"))

# A tibble: 3 × 3
  year  month day  
    
1 2001  01    01   
2 2002  02    02   
3 2003  03    03 

separate_wider_position()で展開

サンプルデータフレームで、列xを「-」で展開するには次のようにします。


df |>
  separate_wider_position(x, c(year = 4, 1, month = 2, 1, day = 2))

# A tibble: 3 × 3
  year  month day  
    
1 2001  01    01   
2 2002  02    02   
3 2003  03    03 

separate_wider_regex()で展開

サンプルデータフレームで、列xを「-」で展開するには次のようにします。


df |>
  separate_wider_regex(x, c(year = ".*", "-", month = ".*", "-", day = ".*"))

# A tibble: 3 × 3
  year  month day  
    
1 2001  01    01   
2 2002  02    02   
3 2003  03    03  
R入門 データフレームで文字列を複数の列に分割する方法