Skip to content

R でのデータインポート: 高速・正確・再現可能な読み込み

問題

ファイル読み込みの遅さや文字化けが、分析が始まる前にプロジェクトを頓挫させてしまう。チームは CSV や Excel ファイルが届くたびに、毎回インポートコードを書き直す羽目になっている。

問題の深刻化

エンコーディング設定が誤っていると非 ASCII 文字が壊れ、ID から先頭ゼロが消え、大きな CSV はメモリを圧迫する。実行のたびに結果が変わることで、データセットへの信頼は失われ、モデリングやレポーティングの開始がどんどん遅れていく。

解決策

用途別に設計された R のリーダー関数を使い、ロケール・区切り文字・型を明示的に制御する。以下のパターンを使えば、読み込みは高速で、型は安定し、マシンが変わっても再現可能なインポートが実現できる。

CSV と TSV: readr のデフォルト + ロケールの明示

library(readr)
 
orders <- read_csv(
  "data/orders.csv",
  locale = locale(encoding = "UTF-8", decimal_mark = ".", grouping_mark = ","),
  col_types = cols(
    order_id = col_character(),
    order_date = col_date(format = "%Y-%m-%d"),
    revenue = col_double(),
    region = col_character()
  )
)
  • col_types を指定して、R が勝手に factor を推測したり ID をトリムしたりしないようにする。
  • タブ区切りファイルには read_tsv()、セミコロン区切りには read_delim(delim = ";") を使う。

Excel: xls/xlsx には readxl

library(readxl)
 
budget <- read_excel(
  "data/budget.xlsx",
  sheet = "FY24",
  range = "A1:G200",
  col_types = c("text", "numeric", "numeric", "date", "text", "numeric", "numeric")
)
  • readxl は Java を必要とせず、セルのフォーマットを安定して扱える。
  • skip = でヘッダ行を間引き、range で必要な範囲だけを読むことで高速化できる。

大きな CSV: data.table::fread

library(data.table)
 
clicks <- fread(
  "data/clicks.csv",
  encoding = "UTF-8",
  colClasses = list(character = "user_id"),
  nThread = 4
)
  • 区切り文字は自動検出されるが、必要なら sep = "\t" のように上書きできる。
  • select = を使って必要な列だけ読み込めば、メモリ消費を抑えられる。

列指向 & 多言語データ: arrow

library(arrow)
 
events <- read_parquet("data/events.parquet", as_data_frame = TRUE)
 
# 大規模データセットをバッチでストリーミングする場合
ds <- open_dataset("s3://bucket/events/")  # ローカルのフォルダにも同様に使える
events_summary <- ds %>%
  filter(country %in% c("DE", "FR")) %>%
  group_by(country) %>%
  summarise(count = n())
  • Arrow は型を保持し、デフォルトで UTF-8 を扱う。
  • Python/SQL エンジンとの相互運用や、メモリに載せきれないデータのフィルタリングに向いている。

エンコーディングと区切り文字の扱い

  • 多言語データでは常に encoding を明示し、可能ならエンドツーエンドで UTF-8 を採用する。
  • ヨーロッパ圏の CSV では、locale(decimal_mark = ",", grouping_mark = ".") を指定する。
  • 区切り文字が一定でない場合は、read_delim(..., n_max = 20) で一部だけ読み、パース結果を確認する。

簡易ベンチマーク(100 万行・8 列・SSD)

ReaderFile typeApprox. load timeMemory footprintNotes
data.table::freadCSV約 3–4 秒フラットファイルで最速クラス。型推測も良好。
readr::read_csvCSV約 6–8 秒低〜中パースエラーが分かりやすく、ロケール制御が優秀。
arrow::read_parquetParquet約 2–3 秒列指向。遅延フィルタリングや複数ファイルのデータセットに対応。
readxl::read_excelXLSX約 8–12 秒ビジネス用途のワークブックに最適だが、非常に横に広いシートではやや遅い。

時間はハードウェアによって変わるため、この表は相対的な目安として扱う。

再現可能なインポートのチェックリスト

  • col_typescolClasses で列型を固定する。
  • localeencoding を明示し、見えない文字化けを防ぐ。
  • スキーマは「薄く」保ち、インポート時に不要な列は落とす。
  • 読み込み後すぐに nrow()summary() を記録し、異常を早期検知する。

関連ガイド