RでのCSVファイルの読み書き:readrの完全ガイド
最初の10回のレッスンでは、R内のデータに焦点を当ててきましたが、実際のプロジェクトでは、データの99%が外部ファイルに保存されています。このレッスンでは、最も一般的に使用されるデータ形式であるCSVファイルについて学びます。Rでは、CSVファイルの読み書きに2つの方法があります。標準的なRの方法
read.csvと、tidyverseの方法readrです。後者の方がよりスマートで高速です。
このレッスンを修了すると、5秒で1,000行の売上データをRに取り込み、整理されたレポートを作成できるようになります。
1. 学習内容
- CSVファイルとは何ですか?また、データサイエンスでなぜ使われるのですか?
- 基本的なR
read.csvとtidyversereadrの違い read_csv()8つの一般的なパラメータ(col_types、na、skip、n_maxなど)write_csv()レポートを生成する- よくある問題への対処(エンコーディング、欠損値、区切り文字)
- 大容量ファイルの読み込みに関するヒント(チャンキング、型最適化)
2. データインポートにおける課題
(1) 課題:ExcelからRへの変換によりシステムがフリーズする
チェンはアナリストで、上司から売上データが記載された100 MBのCSVファイルが送られてきました:
id,date,product,region,amount
1,2024-01-15,Cell Phone,Beijing,2999
2,2024-01-15,Computer,Shanghai,5999
3,2024-01-16,Cell Phone,Guangzhou,2899
...
(@,000 rows of)
彼はread.csv()を使用してデータを読み込み、30秒待った後、@,000行を印刷するのにさらに10秒かかった。また、5つの列すべてがchr型(数値が文字列として扱われる)であることも判明した。
(2) Rを用いた解決策
# 1. Use readr Smart Reading(5 s)
library(readr)
sales <- read_csv("sales.csv")
# 2. Automatic Type Inference
# id → integer, date → date, product → character,
# region → character, amount → double
# 3. Read only the rows you need(Speed Up 3x)
sales_sample <- read_csv("sales.csv", n_max = 10000)
# 4. Write clean reports
write_csv(sales_sample, "sales_clean.csv")
コード1行=30秒 → 5秒。これこそがreadrの真価です。
3. CSVとは何ですか?
(1) CSV = カンマ区切り値
Name,Age,City
Alice,25,Beijing
Bob,30,Shanghai
Charlie,35,Guangzhou
- 1行につき1レコード
各フィールドは
,(または;、|、\t)で区切ってください。 - 1行目は通常、列名(ヘッダー)です
- カンマを含むフィールドを処理するための文字列の引用符
"..."をサポートしています
(2) なぜCSVはデータサイエンスの分野でこれほど広く使われているのでしょうか?
| メリット | 説明 |
|---|---|
| 概要 | Excel、Python、R、およびデータベースに対応 |
| 人間が読みやすい形式 | メモ帳で直接表示可能 |
| ファイルサイズが小さい | Excelの5~10分の1 |
| クロスプラットフォーム | Excelのバージョン違いによる文字化けがない |
| 扱いやすい | Excelの書式設定や数式のノイズがない |
graph LR
A[CSV Documents<br/>name,age,city] --> B[read_csv Smart Reading]
B --> C[tibble Clean DataFrame]
C --> D[write_csv Reports]
C --> E[dplyr Analysis]
C --> F[ggplot2 Visualization]
style A fill:#cce5ff
style B fill:#d4edda
style C fill:#fff3cd
style D fill:#f8d7da
style E fill:#e1d4ff
style F fill:#ffe1d4
4. 基本のRとtidyverse:CSVファイルを扱う2つのアプローチ
mindmap
root((CSV Read/write<br/>Two Options))
Basics R
read.csv
write.csv
Slow
String Conversion factor
tidyverse
readr
read_csv
write_csv
read_tsv
Advantages
Intelligent Type Inference
Fast 5-10x
Large File Progress Bar
Strings are not converted factor
Selection Recommendations
New Project: tidyverse
Legacy code: read.csv + stringsAsFactors = FALSE
GB Level data: data.table::fread
(1) 2つのアプローチの比較
| 特集 | Base R read.csv |
tidyverse read_csv |
|---|---|---|
| 速度 | 低速(R互換) | 5~10倍高速(C++バックエンド) |
| 型推論 | 弱 (デフォルト: chr) | スマート推論 (int/dbl/date/lgl) |
| 進行状況バー | ❌ | ✅(大容量ファイルでも問題なく動作します) |
| 文字列 | デフォルトで因子に変換 | 文字列のまま保持 |
| 戻り値の型 | data.frame | tibble(より使いやすい) |
| リスト処理 | エラーに寛容 | 自動クリーニング(スペース、特殊文字) |
| 欠損値 | NA |
NA + カスタム文字列 |
| 文字列 | stringsAsFactors = TRUE |
常に FALSE |
(2) 実際の比較
# Basics R(Common Issues with Legacy Code)
df_old <- read.csv("data.csv")
# Default behavior:Convert all string arrays factor(Pitfall!)
# tidyverse(Recommendations)
library(readr)
df_new <- read_csv("data.csv")
# Intelligent Inference Types,Character retains character
readr を使用してください。レガシーコードには、read.csv followed by stringsAsFactors = FALSE を使用してください。
(3) いつ「Basic R」を使うべきか?
| シナリオ | 推奨事項 |
|---|---|
| 新規プロジェクト / 新規コードの記述 | read_csv (readr) |
| GB規模の膨大なデータセットの処理 | data.table::fread (高速化) |
| レガシーコードの保守 | read.csv および stringsAsFactors = FALSE |
| チュートリアル / 簡単なスクリプト | どちらか |
5. read_csv() の 8 つの一般的なパラメータ
(1) 基本的な構文
read_csv(file, col_types = TRUE, col_names = TRUE, na = "NA",
skip = 0, n_max = Inf, locale = default_locale(),
progress = TRUE)
(2) パラメータクイックリファレンス表
| パラメータ | 機能 | デフォルト値 |
|---|---|---|
file |
ファイルパスまたはURL | 必須 |
col_types |
カラム型の指定 | TRUE (自動推論) |
col_names |
TRUE/ベクトル(カスタム列名) | TRUE(最初の行を使用) |
na |
欠損値マーカー | "NA" |
skip |
最初の N 行をスキップ | 0 |
n_max |
読み込む行数の最大値 | Inf (すべて) |
locale |
地域設定(エンコーディング、小数点) | default_locale() |
progress |
進行状況バーを表示 | TRUE |
(3) 実践編:一般的なパラメータ
library(readr)
# 1. Basic Reading(Intelligent Inference Types)
df <- read_csv("data.csv")
# 2. Specify Column Type(Avoiding Fallacies in Reasoning)
df <- read_csv("data.csv", col_types = cols(
id = col_integer(),
date = col_date(format = "%Y-%m-%d"),
amount = col_double(),
name = col_character()
))
# 3. Skip to the beginning 5 Line Comments
df <- read_csv("data.csv", skip = 5)
# 4. Custom NA Mark(CSV For internal use "NULL" Indicates missing)
df <- read_csv("data.csv", na = c("", "NA", "NULL", "N/A"))
# 5. Read-only before 1000 row(For debugging purposes)
df <- read_csv("data.csv", n_max = 1000)
# 6. Skip Column(Use col_types Set as col_skip())
df <- read_csv("data.csv", col_types = cols(
temp_col = col_skip()
))
(4) スマート型推論の詳細な解説
readrの最大の利点は、自動推論です:
| サンプルデータ | 推定結果 |
|---|---|
1, 2, 3 |
integer |
1.5, 2.3 |
double |
2024-01-15 |
date |
12:30:00 |
time |
TRUE, FALSE |
logical |
Beijing, Shanghai |
character |
# Examples of Inference
sales <- read_csv("sales.csv")
spec(sales) # View the inference results
# cols(
# id = col_integer(),
# date = col_date(format = "%Y-%m-%d"),
# product = col_character(),
# region = col_character(),
# amount = col_double()
# )
6. write_csv(): レポートを出力する
(1) 基本的な構文
write_csv(x, file, na = "NA", append = FALSE, col_names = TRUE)
(2) 実践的な応用
# 1. Basic Output
write_csv(sales, "sales_clean.csv")
# 2. Output to the specified path
write_csv(sales, "output/2024_sales.csv")
# 3. Append to the existing file(Do not cover)
write_csv(new_data, "sales.csv", append = TRUE, col_names = FALSE)
# 4. Custom NA indicates
write_csv(df, "output.csv", na = "")
(3) ⚠️ write_csv はデータ型を保持しません
readrがCSVに書き込む際、型の情報は失われます(CSVはプレーンテキストであるため)。それを読み戻す際には、型を再度推論する必要があります:
# Write
write_csv(sales, "sales.csv")
# Read it again
sales_loaded <- read_csv("sales.csv")
# Type by read_csv Re-inference
.rds を使用してください(型の保持)—第12課を参照してください。
7. よくある問題のトラブルシューティング
(1) 文字化けした漢字
# 1. Read Using a Specified Encoding
df <- read_csv("data.csv", locale = locale(encoding = "UTF-8"))
# Or
df <- read_csv("data.csv", locale = locale(encoding = "GBK"))
# 2. Check the file encoding
guess_encoding("data.csv")
# Returns in most cases "UTF-8" or "GBK"
# 3. Specify the encoding when writing
write_csv(df, "output.csv") # Default UTF-8
(2) 区切り文字はコンマではありません
# 1. Tab-separated(TSV)
df <- read_tsv("data.tsv") # sep = "\t"
# 2. Semicolon-separated(Commonly Used in Europe)
df <- read_csv2("data.csv") # sep = ";"
# 3. Custom Delimiters(e.g. |)
df <- read_delim("data.txt", delim = "|")
(3) 千の位区切り記号付きの数値
# European Format:1.234,56(A percentile is .,A decimal is ,)
df <- read_csv("data_eu.csv",
locale = locale(grouping_mark = ".", decimal_mark = ","))
(4) 大容量ファイルの読み込みが遅い
# 1. Read only the required columns(Speed Up 2-3x)
df <- read_csv("big.csv", col_select = c(id, amount))
# 2. Use col_types Skip Column
df <- read_csv("big.csv", col_types = cols(
temp_col_1 = col_skip(),
temp_col_2 = col_skip()
))
# 3. Close the progress bar
df <- read_csv("big.csv", progress = FALSE)
# 4. A Faster Solution:data.table::fread
# fread("big.csv") is 5-10x faster than read_csv
8. 上級編:列タイプの指定 cols()
(1) cols() の完全な構文
col_types = cols(
id = col_integer(), # Integer
name = col_character(), # Character
amount = col_double(), # Double-precision floating-point
date = col_date(), # Date
time = col_time(), # Time
datetime = col_datetime(),# Date and Time
is_active = col_logical(),# Logic
skip = col_skip(), # Skip this column
guess = col_guess() # Let readr infer
)
(2) 文字列の省略表記(より簡潔)
# Use "i" "c" "d" "D" "l" Abbreviation
col_types = cols(
id = "i", # integer
name = "c", # character
amount = "d", # double
date = "D", # date
is_active = "l" # logical
)
# All Inferences(Default)
col_types = TRUE
# Using a list(Sequence-Mapped Columns)
col_types = list(
id = col_integer(),
name = col_character()
)
9. 完全な例:販売データのインポートと分析
以下は、このレッスンで取り上げたすべての概念を結びつけた完全なワークフローの例です。
▶ サンプル:売上データの取り込み + データクレンジング + レポートの作成
# ============================================
# Importing and Processing Sales Data
# Features:Read CSV → Cleaning → Analysis → Generate Report
# ============================================
library(readr)
library(dplyr)
# 1. Preparing Sample Data
sample_data <- tibble(
id = 1:10,
date = as.Date("2024-01-01") + 0:9,
product = c("Cell Phone", "Computer", "Cell Phone", "Tablet", "Cell Phone",
"Computer", "Tablet", "Cell Phone", "Computer", "Cell Phone"),
region = c("Beijing", "Shanghai", "Guangzhou", "Beijing", "Shenzhen",
"Shanghai", "Guangzhou", "Beijing", "Shenzhen", "Shanghai"),
amount = c(2999, 5999, 2899, 3999, 3099,
6299, 3899, 2899, 5999, 3199),
note = c(NA, "Promo", NA, NA, "New Products", NA, NA, "Promo", NA, NA)
)
# Write Example CSV(UTF-8 Coding)
write_csv(sample_data, "sales_demo.csv")
cat("=== The file has been generated ===\n")
# 2. Read CSV(Intelligent Inference)
sales <- read_csv("sales_demo.csv",
na = c("", "NA"),
col_types = cols(
id = col_integer(),
date = col_date(format = "%Y-%m-%d"),
product = col_character(),
region = col_character(),
amount = col_double(),
note = col_character()
))
cat("=== Read the results ===\n")
print(sales)
# 3. Data Quality Check
cat("\n=== Data Structures ===\n")
str(sales)
# 4. Data Analysis
cat("\n=== Sales Statistics ===\n")
summary_stats <- sales |>
group_by(region) |>
summarise(
Number of Orders = n(),
Total Sales = sum(amount),
Average Order = round(mean(amount), 2),
Highest Order = max(amount)
) |>
arrange(desc(Total Sales))
print(summary_stats)
# 5. Find promotional orders
cat("\n=== Promotional Orders ===\n")
promo <- sales |> filter(!is.na(note))
print(promo)
# 6. By Product Category
cat("\n=== Product Sales ===\n")
product_stats <- sales |>
group_by(product) |>
summarise(Sales = n(), Sales = sum(amount))
print(product_stats)
# 7. Generate clean reports
write_csv(summary_stats, "sales_by_region.csv")
write_csv(product_stats, "sales_by_product.csv")
cat("\n=== The report has been generated ===\n")
cat(" - sales_by_region.csv(By Region)\n")
cat(" - sales_by_product.csv(By Product)\n")
# 8. Use RDS Reserved Types(Recommendations)
saveRDS(sales, "sales_clean.rds")
sales_reloaded <- readRDS("sales_clean.rds")
cat("\nRDS Type After Loading:\n")
print(sapply(sales_reloaded, class))
期待される出力(抜粋):
=== Sales Statistics ===
# A tibble: 4 × 5
region Number of Orders Total Sales Average Order Highest Order
`<chr>` `<int>` `<dbl>` `<dbl>` `<dbl>`
1 Beijing 3 9897 3299 3999
2 Shanghai 3 15497 5166. 6299
3 Guangzhou 2 6798 3399 3899
4 Shenzhen 2 9098 4549. 5999
=== Promotional Orders ===
# A tibble: 2 × 6
id date product region amount note
`<int>` `<date>` `<chr>` `<chr>` `<dbl>` `<chr>`
1 2 2024-01-02 Computer Shanghai 5999 Promo
2 8 2024-01-08 Cell Phone Beijing 2899 Promo
❓ よくある質問
locale = locale(encoding = "UTF-8") または "GBK" を使用してください。エンコーディングがわからない場合は、まず guess_encoding() を試して確認してください。col_select 必要な列のみを読み込む ② col_types 不要な列をスキップする ③ progress = FALSE を無効にする。それでも遅い場合は、data.table::fread を使用してください(より高速になります)。read_csv と fread のどちらを選べばよいですか?read_csv は tidyverse のデフォルト設定であり、dplyr や ggplot2 とよく連携します。fread は処理速度が速い(GB 規模のデータにはこちらが推奨されます)ですが、data.table パッケージのインストールが必要です。ほとんどのプロジェクトでは、read_csvで十分です。📖 まとめ
- CSVは最も汎用性の高いデータ形式です。プレーンテキスト形式で、人間が読みやすく、クロスプラットフォームに対応しており、Excel、Python、R、およびデータベースで読み込むことができます。
- おすすめ:
readr::read_csv—基本版の Rread.csvよりも 5~10 倍高速で、スマートな型推論と Tibble との互換性を備えています - よく使われる8つのパラメータ:
col_types(型指定)、na(NAフラグ)、skip、n_max、col_select、locale、progress、col_names - 自動型推論:整数 / 倍精度浮動小数点数 / 日付 / 時刻 / 日付時刻 / ブール値 / 文字列
write_csv()はレポートを出力しますが、データ型は保持されません。R内部での永続化にはsaveRDS()またはreadRDS()を使用してください。- 中国語の文字が文字化けしている場合は
locale = locale(encoding = "UTF-8")を使用してください。区切り文字が,でない場合は、read_tsvまたはread_delimを使用してください。 - 大容量ファイルの最適化:
col_select+col_types = col_skip()+ 進行状況表示を無効化
📝 練習問題
-
基本演習:5行4列(id/name/score/date)の
tibbleを作成してください。write_csv()を使用してtest.csvに書き込み、次にread_csv()を使用してそれを読み戻し、型推論が正しいことを確認してください(dateの型はDateです)。 -
基本演習:前の問題の
test.csvを読み、col_types = cols()を使用してすべての列の型を明示的に指定し(id: integer、score: double、name: string、date: date)、それらの型が明示的な指定と一致していることを確認してください。 -
基本演習:NA値を含むデータフレームを作成し(
c(1, NA, 3, NA, 5)を使用)、それをCSV形式でエクスポートした後、na = c("NA", "")を使用して読み込み、NA値が正しく処理されていることを確認してください。 -
応用演習:100行分の販売データ(商品/地域/金額/日付)をシミュレートしてください。
read_csvを使用してデータをインポートした後、① 地域ごとの売上合計を算出する。② 金額が最も高い5件の注文を特定する。③read_csvを使用して、top5.csvとby_region.csvの2つのレポートを生成する。 -
課題:特殊文字(スペースを含む列名、コンマを含む文字列、および区切り文字
|)を含む CSV ファイルを作成し、それぞれread_csvとread_delimを使用して読み込み、結果の違いを比較してください。コンソールの出力をスクリーンショットで撮影し、保存してください。



