4 csvファイルの読み込みと保存
windows環境で過ごしていて日本語を使うRユーザーにおいては、csvファイルを扱う際に文字コードの違いというつらみ(いわゆる文字化け)に遭遇することが少なくありません。
出会う可能性が高い文字コードには、大きくcp932(Shift-JIS)
とUTF-8
という形式があり、一般的に業務で読みこもうとするファイルは前者であることが多いことを知っておくと役に立ちます。
4.1 一つのcsvファイルを読み込む
csvファイルを読みこむには、readr
パッケージのread_csv()
関数を使います。tidyverse
を読み込んだら一緒に読み込まれます。readr
では基本的にutf8
の読み書きが想定されています。RStudioのメニューで以下の部分をUTF-8に変えておかないと、色々つらい思いをします。
Tools > Global Options > Code > Saving > Default text encoding:
Tools > Project Options > Code Editing > text encoding:
data > csv
フォルダ(ここでは>
は階層関係を示し、コードではdata/csv/
で表現)に入っている「ペンギン(ひどい列名)ver_utf8.csv」を開きます。㊛㊚
列のみ、環境依存文字のため、csvにする時点で文字化けています…
4.1.1 UTF-8でエンコードされたcsvファイル
df_csv <-
read_csv("data/csv/ペンギン(ひどい列名)ver_utf8.csv")
df_csv
## # A tibble: 344 × 9
## Spe…¹ `種 類` ※島…² ①クチ…³ ②クチバ…⁴ 翼:…⁵ ■体重…⁶ `㊛㊚`
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Adelie アデリー Torger… 39.1 18.7 181 3750 male
## 2 Adelie アデリー Torger… 39.5 17.4 186 3800 female
## 3 Adelie アデリー Torger… 40.3 18 195 3250 female
## # … with 341 more rows, 1 more variable:
## # `2007~2009` <dbl>, and abbreviated variable names
## # ¹Species, ²`※島の名前`, ³`①クチバシ 長さ(mm)`,
## # ⁴`②クチバシ_大きさ(mm)`, ⁵`翼:長さ(mm)`,
## # ⁶`■体重 単位はg`
4.1.2 Shift-JISでエンコードされたcsvファイル
正確にはShift-JISの拡張版であるcp932でエンコードされたファイルです。Windowsで作られた過去のcsvファイルはこの形式であることが多いです。
4.1.2.1 【エラー例】
以下コードを実行するとエラーが出てきます。
read_csv("data/csv/ペンギン(ひどい列名)ver_cp932.csv")
Error in nchar(x, “width”) : invalid multibyte string, element 1
4.1.2.2 Shift-JISのcsvファイルの読み込み方
これを読むためには,引数locale = locale(encoding = )
でShift-JISのファイルであることを指定する必要があります。
## # A tibble: 344 × 9
## Spec…¹ 種 …² ※島…³ ①クチ…⁴ ②クチバ…⁵ 翼:…⁶ ■体重…⁷ `??`
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Adelie アデリ… Torger… 39.1 18.7 181 3750 male
## 2 Adelie アデリ… Torger… 39.5 17.4 186 3800 female
## 3 Adelie アデリ… Torger… 40.3 18 195 3250 female
## # … with 341 more rows, 1 more variable:
## # `2007~2009` <dbl>, and abbreviated variable names
## # ¹Species, ²`種 類`, ³`※島の名前`,
## # ⁴`①クチバシ 長さ(mm)`, ⁵`②クチバシ_大きさ(mm)`,
## # ⁶`翼:長さ(mm)`, ⁷`■体重 単位はg`
4.1.3 read.csv()を使う場合
従来のcsvを読む関数read.csv()
を使う場合も同様です。R-4.2からはデフォルトでUTF-8を読むようになったため,Shift-JISのファイルを読むためには引数で指定する必要があります。
read.csv("data/csv/ペンギン(ひどい列名)ver_cp932.csv",
fileEncoding = "cp932") |>
as_tibble() # データフレームをtibble型にし見やすい出力に
## # A tibble: 344 × 9
## Speci…¹ 種.類 X.島…² X.ク…³ X.クチバ…⁴ 翼.長…⁵ X.体…⁶ X..
## <chr> <chr> <chr> <dbl> <dbl> <int> <int> <chr>
## 1 Adelie アデ… Torger… 39.1 18.7 181 3750 male
## 2 Adelie アデ… Torger… 39.5 17.4 186 3800 female
## 3 Adelie アデ… Torger… 40.3 18 195 3250 female
## # … with 341 more rows, 1 more variable:
## # 2007.2009 <int>, and abbreviated variable names
## # ¹Species, ²X.島の名前, ³X.クチバシ.長さ.mm.,
## # ⁴X.クチバシ.大きさ.mm., ⁵翼.長さ.mm., ⁶X.体重.単位はg
UTF-8を読む場合はデフォルトで読めます。
## # A tibble: 344 × 9
## Speci…¹ 種.類 X.島…² X.ク…³ X.クチバ…⁴ 翼.長…⁵ X.体…⁶ X..
## <chr> <chr> <chr> <dbl> <dbl> <int> <int> <chr>
## 1 Adelie アデ… Torger… 39.1 18.7 181 3750 male
## 2 Adelie アデ… Torger… 39.5 17.4 186 3800 female
## 3 Adelie アデ… Torger… 40.3 18 195 3250 female
## # … with 341 more rows, 1 more variable:
## # 2007.2009 <int>, and abbreviated variable names
## # ¹Species, ²X.島の名前, ³X.クチバシ.長さ.mm.,
## # ⁴X.クチバシ.大きさ.mm., ⁵翼.長さ.mm., ⁶X.体重.単位はg
4.1.4 大きいデータならfread()
これまで紹介したcsvファイルを読みこむための関数は、小規模なデータならそんなに時間はかかりませんが、データが数万行×数百列と大きくなってくると、時間がかかるようになります。
そこで大きく時間を短縮できるのが、data.table
パッケージのfread()
関数です。
UTF-8を読む場合はデフォルトで読めます。data.frame形式にするには引数にdata.table = FALSE
をつけます
## # A tibble: 344 × 9
## Spe…¹ `種 類` ※島…² ①クチ…³ ②クチバ…⁴ 翼:…⁵ ■体重…⁶ `㊛㊚`
## <chr> <chr> <chr> <dbl> <dbl> <int> <int> <chr>
## 1 Adelie アデリー Torger… 39.1 18.7 181 3750 male
## 2 Adelie アデリー Torger… 39.5 17.4 186 3800 female
## 3 Adelie アデリー Torger… 40.3 18 195 3250 female
## # … with 341 more rows, 1 more variable:
## # `2007~2009` <int>, and abbreviated variable names
## # ¹Species, ²`※島の名前`, ³`①クチバシ 長さ(mm)`,
## # ⁴`②クチバシ_大きさ(mm)`, ⁵`翼:長さ(mm)`,
## # ⁶`■体重 単位はg`
R4.2からは,Shift-JISのファイルを読むと日本語が文字化けするようになってしまいました。現在の所,これは対処不可能みたいです。
4.1.5 大きいデータを読む場合のvroom
readr
を速くしたようなパッケージにvroom
[https://vroom.r-lib.org/]があります。しばらくは別々に開発が進むみたいですが,将来的に統合が考えられてるらしいです。shift-jisの大規模csvファイルを読む際のfread
に代わる選択肢として有望です
vroom::vroom("data/csv/ペンギン(ひどい列名)ver_utf8.csv")
## # A tibble: 344 × 9
## Spe…¹ `種 類` ※島…² ①クチ…³ ②クチバ…⁴ 翼:…⁵ ■体重…⁶ `㊛㊚`
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Adelie アデリー Torger… 39.1 18.7 181 3750 male
## 2 Adelie アデリー Torger… 39.5 17.4 186 3800 female
## 3 Adelie アデリー Torger… 40.3 18 195 3250 female
## # … with 341 more rows, 1 more variable:
## # `2007~2009` <dbl>, and abbreviated variable names
## # ¹Species, ²`※島の名前`, ³`①クチバシ 長さ(mm)`,
## # ⁴`②クチバシ_大きさ(mm)`, ⁵`翼:長さ(mm)`,
## # ⁶`■体重 単位はg`
Shift-JISのファイルはreadr
と同じように引数で指定します
## # A tibble: 344 × 9
## Spec…¹ 種 …² ※島…³ ①クチ…⁴ ②クチバ…⁵ 翼:…⁶ ■体重…⁷ `??`
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Adelie アデリ… Torger… 39.1 18.7 181 3750 male
## 2 Adelie アデリ… Torger… 39.5 17.4 186 3800 female
## 3 Adelie アデリ… Torger… 40.3 18 195 3250 female
## # … with 341 more rows, 1 more variable:
## # `2007~2009` <dbl>, and abbreviated variable names
## # ¹Species, ²`種 類`, ³`※島の名前`,
## # ⁴`①クチバシ 長さ(mm)`, ⁵`②クチバシ_大きさ(mm)`,
## # ⁶`翼:長さ(mm)`, ⁷`■体重 単位はg`
4.2 複数のcsvファイルを読み込む
2.3で紹介した方法で,読み込みの関数をread_csv()
に変えるだけで同じことができますが,もっと簡単な方法もあります。
まず,csvファイルのパス一覧を取得します。
files <-
list.files(path = "data/複数/", full.names = TRUE)
files <-
files |>
str_subset("csv")
files
## [1] "data/複数/Adelie.csv" "data/複数/Chinstrap.csv"
## [3] "data/複数/Gentoo.csv"
この3つのcsvファイルを一気に読み込んで縦につなげたいとします。
これは,read_csv()
の第一引数にパス一覧オブジェクトを入れ,id =
引数にファイル名の情報を示す列の名前(ここではfile_name
)を決めるだけです。
`
read_csv(files, id = "file_name")
## # A tibble: 344 × 9
## file_name species island bill_…¹ bill_…² flipp…³ body_…⁴ sex
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 data/複数… Adelie Torge… 39.1 18.7 181 3750 male
## 2 data/複数… Adelie Torge… 39.5 17.4 186 3800 fema…
## 3 data/複数… Adelie Torge… 40.3 18 195 3250 fema…
## # … with 341 more rows, 1 more variable: year <dbl>, and
## # abbreviated variable names ¹bill_length_mm, ²bill_depth_mm,
## # ³flipper_length_mm, ⁴body_mass_g
4.3 csvファイルの保存
csvファイルを保存するには、readr
パッケージのwrite_csv()
関数を使います。ただし、出力されたcsvファイルをExcelでそのまま開くとたぶん文字化けするので,インポートなどの操作が必要かもしれません。LibreOfficeのCalcであれば、最初にダイアログボックスが開いて読む文字コードを選べます。
4.3.1 write_csv()を使う
先ほど読みこんだdf_csv
と、保存先を""
中に指定します。
write_csv(df_csv, "out/df_csv_utf8.csv")
4.3.1.1 Excelで開いても読めるように
Excelで開いても読める、BOM(byte order mark, バイトオーダーマーク)付きファイルとして出力する関数です。
write_excel_csv(df_csv, "out/df_csv_utf8_forxl.csv")