potisanのプログラミングメモ

プログラミング素人です。昔の自分を育ててくれたネット情報に少しでも貢献できるよう、情報を貯めていこうと思っています。Windows環境のC++やC#がメインです。

R readr 2.1.5 readme 和訳・改変

Rのパッケージreadr 2.1.5のリファレンス和訳です。readrはHadley Wickham氏の作成したtidyverseの一部で、CSV等の長方形データセットを読み込む機能を提供します。

原文はMITライセンスですが、原文の権利はHadley Wickham氏と貢献者方にあります。翻訳文の使用は自己責任です。

readr

概要

readrの目的はCSV (カンマ区切り値)やTSV (タブ区切り値)のような区切られたファイルから長方形データを読み込む高速で使いやすい方法の提供です。野生で見つかる多くのデータ型を解析できるように設計されており、予期しない結果が得られた場合は分かりやすいレポートを提供します。readrを初めて使う場合はR for Data Scienceの「data import chapter」を読むと良いでしょう。

インストール

# tidyverseの一部としてreadrを入手するのが一番簡単です。
install.packages("tidyverse")

# readrだけのインストールも可能です。
install.packages("readr")

使い方

readrはtidyverseコアの一部です。次の方法で読み込めます。

library(tidyverse)
#> ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
#> ✔ dplyr     1.1.4          ✔ readr     2.1.4.9000
#> ✔ forcats   1.0.0          ✔ stringr   1.5.1     
#> ✔ ggplot2   3.4.3          ✔ tibble    3.2.1     
#> ✔ lubridate 1.9.3          ✔ tidyr     1.3.0     
#> ✔ purrr     1.0.2          
#> ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
#> ✖ dplyr::filter() masks stats::filter()
#> ✖ dplyr::lag()    masks stats::lag()
#> ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

もちろん個別のパッケージとしても読み込めます。

library(readr)

readrで長方形データセットを読み込むには二つのピースを組み合わせます。ファイルの各行を解析して個々のフィールドにする関数と列仕様です。

readrは以下のファイルフォーマットをread_*()関数によりサポートします。

  • read_csv():カンマ区切り値(CSV)
  • read_tsv():タブ区切り値(TSV)
  • read_csv2(),を小数点区切りとしたセミコロン区切り値
  • read_delim():区切りファイル(CSVやTSVは重要な特殊例)
  • read_fwf():固定幅ファイル
  • read_table():空白区切りファイル
  • read_log():ウェブログファイル

列仕様は各列を文字列ベクトルから特定のデータ型(文字列、数値、日時等)へ変換する方法を記述します。列仕様が指定されない場合、readrはデータから列の型を推測します。readrの列の型推測に関する詳細はvignette("column-types")を確認してください。列の型推測は特にデータ探索においてとても手軽です。しかし「推測でしかない」ことは忘れないでください。任意のデータ解析プロジェクトが探索段階よりも成熟した場合、列の型の明示的な提供は最善の方法です。

以下の具体例ではreadrにバンドルされたサンプルファイルを読み込み、列の型を推測しています。

(chickens <- read_csv(readr_example("chickens.csv")))
#> Rows: 5 Columns: 4
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> chr (3): chicken, sex, motto
#> dbl (1): eggs_laid
#> 
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#> # A tibble: 5 × 4
#>   chicken                 sex     eggs_laid motto                               
#>   <chr>                   <chr>       <dbl> <chr>                               
#> 1 Foghorn Leghorn         rooster         0 That's a joke, ah say, that's a jok…
#> 2 Chicken Little          hen             3 The sky is falling!                 
#> 3 Ginger                  hen            12 Listen. We'll either die free chick…
#> 4 Camilla the Chicken     hen             7 Bawk, buck, ba-gawk.                
#> 5 Ernie The Giant Chicken rooster         0 Put Captain Solo in the cargo hold.

readrは列の型、この場合は推測した列の型を出力することに注意してください。読み込んだ列が期待通りかチェックできる便利な機能です。期待と異なる場合は列仕様の提供が必要です。多くのトラブルがあるように感じますが、幸運にもreadrは作業に良い流れをもたらします。spec()を使い、初期の努力から(推測した)列仕様を取得してみましょう。

spec(chickens)
#> cols(
#>   chicken = col_character(),
#>   sex = col_character(),
#>   eggs_laid = col_double(),
#>   motto = col_character()
#> )

コピペして調整すれば、求める列の型を表現するより明示的なreadrの呼び出しを作成できます。ここでsexroosterhenを水準としたファクター、eggs_laidは整数を表すとしましょう。

chickens <- read_csv(
  readr_example("chickens.csv"),
  col_types = cols(
    chicken   = col_character(),
    sex       = col_factor(levels = c("rooster", "hen")),
    eggs_laid = col_integer(),
    motto     = col_character()
  )
)
chickens
#> # A tibble: 5 × 4
#>   chicken                 sex     eggs_laid motto                               
#>   <chr>                   <fct>       <int> <chr>                               
#> 1 Foghorn Leghorn         rooster         0 That's a joke, ah say, that's a jok…
#> 2 Chicken Little          hen             3 The sky is falling!                 
#> 3 Ginger                  hen            12 Listen. We'll either die free chick…
#> 4 Camilla the Chicken     hen             7 Bawk, buck, ba-gawk.                
#> 5 Ernie The Giant Chicken rooster         0 Put Captain Solo in the cargo hold.

vignette("readr")を使えばreadrの拡張された導入を確認できます。

エディション

readrはバージョン2.0.0(2021年7月公開)から新しい解析エンジンを手に入れました。この第2エディションでは、readerは既定でvroom::vroom()を呼び出します。

readrバージョン2.0.0未満の解析エンジンを第1エディションと呼びます。2.0.0以降のreadrを使う場合もwith_edition(1, ...)関数とlocal_edition(1)関数により第1エディションの解析にアクセスできます。バージョン2.0.0未満のreadrを使う場合、第1エディションの解析を使うことは明らかです。

いくつかのリリースで第1エディションのサポートを続けますが、全体的な目的は第2エディションを第1エディションよりも一様に良くすることです。最終的には第1エディションのコードを非推奨として、削除する計画です。with_edition(1, ...)local_edition(1)による回避策はレガシーコードの実用的な応急処置ですが、第2エディションが成熟すれば不適切な一時的解決策です。

代替手段

readrには2つの主要な代替手段があります。base Rとdata.tableのfread()です。最も重要な違いは以下で議論します。

Base R

対応するbase関数と比べてreadr関数は以下の特徴を持ちます。

  • 引数の一貫した名前スキーム(例えば、headercolClassesではなくてcol_namescol_types)。

  • データセット依存ですが一般的にはるかに高速(10~100倍以上)。

  • 文字列は既定のままで、一般的な日時フォーマットは自動的に解析します。

  • 時間がかかる処理の便利なプログレスバーがあります。

  • 全ての関数が現在のロケールに関わらず正確に同じ方法で動作します。US中心の既定値を上書きするにはlocale()を使用します。

data.tableとfread()

data.tableにはfread()というread_csv()に似た関数があります。fread()と比べてreadrは以下の特徴を持ちます。

  • しばしばより遅いです。特に重い数値データにおいて。

  • いくつかの引数を自動的に推測できます。ただし、基本的には明確な指定を推奨します。例えば区切り文字、スキップする行やヘッダー行についてです。

  • tidyverseワイドな慣習、例えばtibble型の戻り値、列名修復のような標準手法、列選択用の共通のミニ言語に従います。

謝辞

以下の方々へのお礼を述べます。

  • Joe Chengは解析に関する決定性有限オートマタの美しさを見せてくれました。また、トークナイザーを書くべき理由を教えてくれました。

  • JJ Allaireはコピーがとても少なくて拡張の用意なデザインを思い付く助けをくれました。

  • Dirk Eddelbuettelは名前を考えてくれました!