-
Notifications
You must be signed in to change notification settings - Fork 6
/
io.qmd
304 lines (201 loc) · 21 KB
/
io.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# データの入出力 {#sec-io}
```{r io-common}
#| include: false
source("_common.R")
```
この章で使うパッケージを読み込む。
```{r io-setup}
#| message: false
#| warning: false
pacman::p_load(tidyverse, readxl, haven)
```
## データの読み込み {#sec-io-read}
### CSVファイルの場合
データの保存によく利用される保存形式として、CSVファイルがある。CSV とは、comma separated values の略である。多くの人に馴染みがあると思われる Excelファイル (.xlsx) と同じように、表形式(行列形式)のデータを保存することができる。しかし、Excelファイルとは異なり、文字の大きさ、セルの背景色、複数のセルの結合のような情報はもたず、純粋にデータに含まれる変数の名前と各変数の値(数値・文字列)のみが格納されているため、ファイルサイズが小さい。文字データしかもたないテキストファイルなので、テキストエディタでも開くことができる。テキストエディタでCSVファイルを開けば、これが "CSV" と呼ばれる理由がわかるだろう。CSVフォーマットはデータを保存のための標準フォーマットの1つであり、多くのデータがCSV形式で保存されている。現存するデータ分析ソフトでCSV ファイルを開けないものはおそらくないだろう。
RでもCSV形式のファイルは簡単に読み込める。実際にやってみよう。例として利用するデータのダウンロード方法については本書の、[巻頭](https://www.jaysong.net/RBook/#%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89)を参照されたい。CSVファイルに保存されたデータをRで読み込むには`read.csv()`または`readr::read_csv()`関数を使う[^io-readcsv1]。読み込む際は[前章](r_basic.html)のベクトルの生成同様、何らかの名前を付けて作業環境に保存する。`Data`フォルダにある `FIFA_Women.csv` ファイルを読み込み、`my_df1`と名付ける場合、以下のようなコードを実行する[^io-readcsv2]。以下のコードで`my_df1 <-` の部分を入力しないと、データが画面に出力され、自分の作業スペースには保存されないので注意されたい。
[^io-readcsv1]: `read.csv()`で読み込まれた表は `data.frame` クラス、`read_csv()`関数で読み込まれた表は `tibble` クラスとして保存される。詳細は[-@sec-datastructure-dataframe]節で解説する。
[^io-readcsv2]: Rのバージョンが4.0.0 未満の場合は、引数として`stringsAsFactors = FALSE` を追加する。たとえば、`my_df1 <- read.csv("Data/FIFA_Women.csv", stringsAsFactors = FALSE)` とする。これを追加しないと、文字列で構成されている列が `factor` 型として読み込まれる。
```{r io-read-1}
my_df1 <- read.csv("Data/FIFA_Women.csv")
```
読み込まれたデータの中身を見るには、ベクトルの場合と同様に`print()`関数を使うか、オブジェクト名を入力する。すると、データ全体が表示される。ただし、表示できる列数・行数に限りがあるため、あまりにも大きなデータの場合は一部のみ表示される[^data-print-note1]。
[^data-print-note1]: R MarkdownファイルまたはQuarto ファイルでインライン表示している場合には、最初の10行のみ表示される。
```{r io-read-2}
my_df1
```
しかし、通常はデータが読み込まれているかどうかを確認するためにデータ全体を見る必要はない。最初の数行のみで問題ないはずだ。そのために、`head()` 関数を使う。これは最初の6行 (`n` で表示行数を変えることができる) を表示してくれる。
```{r io-read-3}
head(my_df1)
```
同様に、最後の `n`行は`tail()` で表示する。
```{r io-read-4}
tail(my_df1, n = 9)
```
ただし、今後は特殊な事情がない限り`read.csv()`は使用せず、`readr::read_csv()`を使う。基本的な使い方は同じである。`read_csv()`は{tidyverse}の一部である{readr}パッケージに含まれる関数であるため、あらかじめ{tidyverse}(または{readr}そのもの)を読み込んでおく必要がある。
```{r io-read-5}
#| message: false
pacman::p_load(tidyverse)
my_df1 <- read_csv("Data/FIFA_Women.csv")
my_df1
```
同じファイルが読み込まれたが、データを出力すると最初の10行のみが表示される。画面に収まらない大きさのデータであれば、適宜省略し、見やすく出力してくれる。`read_csv()`で読み込まれたデータは、tibbleと呼ばれるやや特殊なものとして格納される。Rがデフォルトで提供する表形式データの構造はdata.frameだが、tibbleはその拡張版である。詳しくは第[-@sec-datastructure-dataframe]章を参照されたい。
### エンコーディングの話
`Vote_ShiftJIS.csv` はShift-JIS でエンコーディングされた csvファイルである。このファイルを `read.csv()` 関数で読み込んでみよう。
```{r io-encoding-1}
#| error: true
ShiftJIS_df <- read.csv("Data/Vote_ShiftJIS.csv")
```
Windowsならなんの問題なく読み込まれるだろう。しかし、macOSの場合、以下のようなエラーが表示され、読み込めない。
```
## Error in type.convert.default(data[[i]], as.is = as.is[i], dec = dec, : '<96>k<8a>C<93><b9>' に不正なマルチバイト文字があります
```
このファイルは、`read.csv()`の代わりに {readr}パッケージの`read_csv()`を使えば読み込むことができる[^io-readr]。`read_csv()`で読み込み、中身を確認してみよう。
```{r io-encoding-2}
#| message: false
ShiftJIS_df1 <- read_csv("Data/Vote_ShiftJIS.csv")
head(ShiftJIS_df1)
```
2列目の`Pref`列には日本語で都道府県名が入っているはずだが、謎の文字列が表示される。Windows で`read.csv()`を使ったなら、このファイルは問題なく読み込めたはずだ。それは、`read.csv()`がWindowsではShift-JISを、macOSではUTF-8をファイルの文字コードとして想定しているためだ。一方、`read_csv()`はOSにかかわらず世界標準であるUTF-8でファイルを読み込む。
[^io-readr]: readr パッケージは tidyverse の一部なので、上で読み込み済みである。
正しい都道府県名を表示する方法はいくつかあるが、ここでは3つの方法を紹介する。
**1. `read.csv()`関数の`fileEncoing`引数の指定**
第1の方法は、`read.csv()`関数の `fileEncoding ` 引数を追加するというものである。この引数に、開きたいファイルで使われている文字コードを指定すればよい。Shift-JISの場合、`"Shift_JIS"` を指定する。ハイフン (`-`)ではなく、アンダーバー (`_`) であることに注意されたい。この`"Shift_JIS"`は`"cp932"` に書き換えても良い。それではやってみよう。
```{r io-encoding-3}
ShiftJIS_df2 <- read.csv("Data/Vote_ShiftJIS.csv",
fileEncoding = "Shift_JIS")
head(ShiftJIS_df2)
```
`Pref`列の日本語が正常に表示された。繰り返しになるが、Windowsなら`fileEncoding`引数がなくても正しく読み込める。むしろ、UTF-8で書かれたファイルが読み込めない可能性がある。WindowsでUTF-8のファイルを読み込みときは、`fileEncoding = "UTF-8"`を指定するとよい。
**2. `read_csv()`関数の`locale`引数の指定**
第2の方法は、 `read_csv()` 関数の`locale` 引数を指定する方法である。`read_csv()`には `fileEncoding `という引数の代わりに `locale` があるので、`locale = locale(encoding = "Shift_JIS")`を追加する。
```{r io-encoding-4}
#| message: false
ShiftJIS_df3 <- read_csv("Data/Vote_ShiftJIS.csv",
locale = locale(encoding = "Shift_JIS"))
head(ShiftJIS_df3)
```
**3. LibreOfficeなどを利用する方法**
第3の方法は、そもそも Shift-JISでではなく、より一般的な UTF-8 でエンコーディングされたファイルを用意し、それを読み込むことである。ただし、この作業のためにはR以外のソフトが必要である。テキストエディタには文字コードを変更する機能がついているものが多いので、その機能を利用して文字コードを Shift-JISからUTF-8に変えればよい。また、オープンソースのオフィススイートである [LibreOffice](https://ja.libreoffice.org/) は、CSVを開く際に文字コードを尋ねてくれるので、Shift-JIS を指定してCSV ファイルを開こう。その後、開いたファイルの文字コードをUTF-8に変更し、別名でCSVファイルを保存すれば、文字コード以外の中身が同じファイルができる。そのようにして作ったのが、`Vote.csv` である。これを読み込んでみよう。
```{r io-encoding-5}
#| include: false
if (Sys.info()["sysname"] == "Windows") {
UTF8_df <- read.csv("Data/Vote.csv", fileEncoding = "UTF-8")
} else {
UTF8_df <- read.csv("Data/Vote.csv")
}
```
```{r io-encoding-6}
#| eval: false
UTF8_df <- read.csv("Data/Vote.csv") # macOSの場合
UTF8_df <- read.csv("Data/Vote.csv", fileEncoding = "UTF-8") # Windowsの場合
```
```{r io-encoding-7}
head(UTF8_df)
```
macOSでは第1引数以外の引数を何も指定しなくても、ファイルが正しく読み込まれ、都道府県名が日本語で表示されている。ただし、Windowsで文字化けが生じる場合はファイルのエンコーディングをUTF-8に指定して読み込もう。
### その他のフォーマット
データ分析で用いられるデータの多くは表の形で保存されている。表形式のデータは、`.csv`以外に、`.xlsx` (Excel)、`.dta` (Stata)、`.sav` (SPSS)、`.ods` (LibreOfficeなど) などのファイル形式で保存されることがある。ここでは接する機会が多い Excel 形式のファイルと Stata 形式のファイルの読み込みについて説明しよう[^io-read1]。
Excelファイルを読み込むためには**readxl**パッケージを使う。インストールされていない場合、コンソール上で`install.packages("readxl")`を入力し、インストールする(上で `pacman::p_load(readxl)` を実行したのでインストールされているはずだが)。以下では**readxl**パッケージがインストールされていると想定し、`Soccer.xlsx`ファイルを読み込み、`Excel_DF`と名付けてみよう。
```{r io-etc-1}
#| warning: false
Excel_DF <- read_xlsx("Data/Soccer.xlsx", sheet = 1)
```
Excelファイルには2つ以上のシートが含まれる場合が多いが、その場合にはどのシートを読み込むかを`sheetIndex ` で指定する。実際、`Soccer.xlsx`ファイルをExcelまたはLibreOffice Calc で開いてみると、シートが3つある。そのうち、必要なデータは1つ目のシートにあるので、ここでは`1`を指定した。きちんと読み込たか確認してみよう。
```{r io-etc-2}
head(Excel_DF)
```
[^io-read1]: `.sav`ファイルは`haven`パッケージの`read_sav()`で、`.ods`は`readODS`パッケージの`read.ods()`関数で読み込める。
Stataの`.dta`ファイルは**haven**パッケージの`read_dta()` 関数を使って読み込む。Stata形式で保存された `Soccer.dta` を読み込み、`Stata_DF`と名付けてみよう。
```{r io-etc-3}
Stata_DF <- read_dta("Data/Soccer.dta")
head(Stata_DF)
```
Excel形式のデータと同じ内容のデータであること確認できる(ただし、変数名は少し異なる)。
社会科学で扱うデータの多くは`.csv`、`.xlsx` (または`.xls`)、`.dta`で提供されるめ、以上のやり方で多くのデータの読み込みができる。
### RDataファイルの場合
データ分析には表形式以外のデータも使われる。データ分析でよく使われるデータの形として、ベクトルや行列のほかに`list`型がある。表形式だけでなく、Rで扱える様々なデータを含むファイル形式の1つが`.RData`フォーマットである。`.RData`にはRが扱える形式のデータを格納するだけでなく、表形式のデータを**複数**格納することができる。また、データだけでなく、分析結果も保存することができる。`.RData`形式のファイルはRでしか読み込めないため、データの保存方法としては推奨できないが、1つのファイルにさまざまなデータが格納できるという大きな長所があるため、分析の途中経過を保存するためにしばしば利用される。
ここでは`Data`フォルダにある`Scores.RData`を読み込んでみよう。このファイルには学生5人の数学と英語の成績に関するデータがそれぞれ`MathScore`と`EnglishScore`という名で保存されている。このデータを読み込む前に、現在の実行環境にどのようなオブジェクトがあるかを `ls()` 関数を使って確認してみよう[^io-ls-rstudio]。
[^io-ls-rstudio]: ちなみにRStudioから確認することもできる。第[-@sec-customize]章のとおりにRStudioを設定した場合、右下ペインの「Environment」タブに現在の実行環境に存在するオブジェクトが表示されているはずだ。
```{r io-rdata-1}
ls()
```
現在の実行環境に`r length(ls())`個のオブジェクトがあることがわかる。
では、`Scores.RData`を読み込んでみよう。`.RData` は、`load()` 関数で読み込む。ただし、これまでのファイルの読み込みとは異なり、保存先のオブジェクト名は指定しない。なぜなら、`.Rdata` の中に既にオブジェクトが保存されているからだ。
```{r io-rdata-2}
load("Data/Scores.RData")
```
ここでもう一度実行環境上にあるオブジェクトのリストを確認してみよう。
```{r io-rdata-3}
ls()
```
`MathScore`と`EnglishScore`という名前のオブジェクトが追加されていることが分かる。
このように、`load()`による`.RData` の読み込みは、`.csv`ファイルや`.xlsx`ファイルの読み込みとは異なる。以下の2点が重要な違いである。
1. `.RData` は、1つのファイルに複数のデータを含むことができる。
2. `.RData`の中にRのオブジェクトが保存されているので、ファイルの読み込みと同時に名前を付けて格納する必要がない。
問題なく読み込まれているか確認するため、それぞれのオブジェクトの中身を見てみよう。
```{r io-rdata-4}
head(MathScore) # MathScoreの中身を出力
tail(EnglishScore) # EnglishScoreの中身を出力
```
## データの書き出し {#sec-io-export}
データを手に入れた時点でそのデータ(生データ)が分析に適した状態であることは稀である。多くの場合、分析をするためには手に入れたデータを分析に適した形に整形する必要がある。この作業を「データクリーニング」と呼ぶが、データ分析の作業全体に占めるデータクリーニングの割合は5割から7割ほどで、大部分の作業時間をクリーニングに費やすことになる。(クリーニングの方法については、データハンドリングの章で説明する。)
データクリーニングが終わったら、生データとクリーニングに使ったコード、クリーニング済みのデータをそれぞれ保存しておこう。クリーニングのコードさえあればいつでも生データからクリーニング済みのデータに変換することができるが、時間的にあまり効率的ではないので、クリーニング済みのデータも保存したほうがよい。そうすれば、いつでもそのデータを読み込んですぐに分析作業に取り組無ことができる[^io-cleaning]。
[^io-cleaning]: 言うまでもないが、データクリーニングのコードと生データも必ず残しておくべきである。
### CSVファイル
データを保存する際にまず考えるべきフォーマットは`.csv` である。データが表の形をしていない場合には次節で紹介する`.RData`フォーマットが必要になるが、多くの場合、データは表の形をしている。読み込みのところで説明したとおり、`.csv`ファイルは汎用的なテキストファイルであり、ほとんどの統計ソフトおよび表計算ソフトで読み込むことができるので、特にこだわりがなければ業界標準のフォーマットとも言える CSV形式でデータ保存しておくのが安全だ[^io-format]。
[^io-format]: Excel (`.xlsx`) も広く使われているが、Excelは有料の商用ソフトであり、持っていない(使える環境にない)人もいることを忘れてはいけない。自分のパソコンに Excel (MS Office)をインストールしていないという人(筆者の1人)もいるのだ。
まずは、架空のデータを作ってみよう。Rにおける表形式のデータは `data.frame`型で表現する。(詳細については第[-@sec-datastructure]章で説明する。)
```{r io-export-1}
my_data <- data.frame(
ID = 1:5,
Name = c("Aさん", "Bさん", "Cさん", "Dさん", "Eさん"),
Score = c(50, 75, 60, 93, 51)
)
```
上のコードを実行すると、`my_data`というオブジェクトが生成され、中には以下のようなデータが保持される。
```{r io-export-2}
my_data
```
このデータを`my_data.csv`という名前のcsvファイルで保存するには、`write.csv()`または`readr::write_csv()`という関数を使う。必須の引数は2つで、1つ目の引数は保存するオブジェクト名、2つ目の引数 `file` は書き出すファイル名である。プロジェクトフォルダの下位フォルダ、たとえばDataフォルダに保存するなら、ファイル名を`"Data/my_ata.csv"`のように指定する。
```{r io-export-3}
#| eval: false
write_csv(my_data, file = "Data/my_data.csv")
```
これを実行すると、プロジェクトのフォルダの中にある `Data` フォルダに`my_data.csv`が生成される。`LibreOffice`や`Numbers`、`Excel`などを使って`my_data.csv`を開いてみると、先ほど作成したデータが保存されていることが確認できる。
![保存したcsvファイルの中身](Figs/IO/Export.png){#fig-io-export-4 width="500px" fig-align="center"}
### RDataファイル
最後に`.RData`形式でデータを書き出してみよう。今回は先ほど作成した`my_data`と、以下で作成する`numeric_vec1`、`numeric_vec2`、`character_vec`を`my_RData.RData`という名のファイルとして `Data`フォルダに書き出す。使用する関数は `save()` である。引数として保存するオブジェクト名をすべてカンマ区切りで書き、最後に`file` 引数でファイル名を指定すればよい。
```{r io-export-5}
numeric_vec1 <- c(1, 5, 3, 6, 99, 2, 8)
numeric_vec2 <- 1:20
character_vec <- c("cat", "cheetah", "lion", "tiger")
save(my_data, numeric_vec1, numeric_vec2, character_vec,
file = "Data/my_RData.RData")
```
実際に`my_RData.Rdata`ファイルが生成されているかを確認してみよう。ファイルの保存がうまくいっていれば、`my_RData.RData`を読み込むだけで、`my_data`、`numeric_vec1`、`numeric_vec2`、`character_vec` という4つのオブジェクトを一挙に作業スペースに読み込むことができるはずだ。実際にできるか確認しよう。そのために、まず現在の実行環境上にある`my_ata`、`numeric_vec1`、`numeric_vec2`、`character_vec`を削除する。そのために `rm()` 関数を使う。
```{r io-export-6}
#| eval: false
rm(my_data)
rm(numeric_vec1)
rm(numeric_vec2)
rm(character_vec)
```
このコードは以下のように1行のコードに書き換えられる。
```{r io-export-7}
rm(list = c("my_data", "numeric_vec1", "numeric_vec2", "character_vec"))
```
4のオブジェクトが削除されたか、`ls()`関数で確認しよう。
```{r io-export-8}
ls()
```
それでは`Data`フォルダー内の`my_RData.RData`を読み込み、4つのオブジェクトが実行環境に読み込まれるか確認しよう。
```{r io-export-9}
load("Data/my_RData.RData") # Dataフォルダー内のmy_RData.RDataを読み込む
ls() # 作業スペース上のオブジェクトのリストを確認する
```
```{r io-export-10}
#| echo: false
#| results: "hide"
file.remove("Data/my_RData.RData")
```