data import/export

はじめに

データ分析で避けて通ることのできないのが読み込み書き出しである。 いつまでもRに内包されているデータセットばかり分析しているわけにはいかない。 もちろんデータ分析はデータが無いと始まらないが、データはどのように保管されているのだろうか。

普段よく目にするcsvやtsvといったテーブル形式のファイルも、中身はただのテキストデータである。

  • csv:カンマで区切られたファイル
  • tsv:タブで区切られたファイル

通常のデータ分析ではこれらデータを読み込み、メモリに広げてから行うことになる。

従来、Rで頻繁に使用されていたのはread.csv()read.tsv()だろう。 しかし、文字列をファクターに変換するのがデフォルトになっていること、windowsではshift-jisがデフォルトの文字コードになっていることなど、欠点が多い。

もちろん、tidyverseはデータ読み込み・書き出し用のパッケージreadrを内包している。 ここではreadrの解説を行う

準備

readrtidyverseに内包されているので

library(tidyverse)

とするだけで良い。

今回はファイルの書き出し、読み込みを行うのでdataというディレクトリを作業ディレクトリの直下に事前に作っておく

read_delim(), write_delim()

csvの読み込みも、tsvの読み込みも区切り文字を指定してやればよい。 そのため、後に紹介するreadrの関数read_csv()read_tsv()もこのread_delim()の特殊な形である。

オプション

指定できるオプションを示す。 主要なものにはコメントを記した。

read_delim(file, # 絶対パスか相対パスを指定、URLなら自動ダウンロード
  delim, # 区切り文字を指定、csvなら delim = ","
  quote = "\"", # 
  escape_backslash = FALSE,
  escape_double = TRUE, 
  col_names = TRUE, # 一行目を変数名にするかどうか。文字列ベクトルで指定することも出来る
  col_types = NULL, # 列タイプをどうするかをベクトルで指定(整数、論理、文字など)基本的にデフォルトでOK
  locale = default_locale(), # 地域によって異なるものを制御することが出来る。文字コードとか
  na = c("", "NA"), 
  quoted_na = TRUE,
  comment = "", 
  trim_ws = FALSE,
  skip = 0, # はじめの難行をスキップするか
  n_max = Inf, # 最大行数。
  guess_max = min(1000, n_max), # progressを示すためのオプション
  progress = show_progress() # 読み込みの進行度を表示するかどうか。しない場合はFALSE
)
write_delim(x, # 保存するオブジェクト
  path, # 保存先のパス
  delim = " ", # 区切り文字を何にするか
  na = "NA", # 欠損している箇所をどのように表記するか
  append = FALSE, 
  col_names = !append # 列名を一行目に書き込むかどうか
)

やってみる

テキストファイルを読み書きしているイメージをつかむために、直接文字列を書いて読み込んでみる。

read_csv("a,b,c
  1,2,3
  4,5,6")
# A tibble: 2 x 3
      a     b     c
  <int> <int> <int>
1     1     2     3
2     4     5     6

改行文字’’を使ってつぎのようにしてもいい

read_csv("a,b,c\n1,2,3\n4,5,hogehoge", # 変な欠損を入れてみた
         na = "hogehoge" # NAを認識するように
)
# A tibble: 2 x 3
      a     b     c
  <int> <int> <int>
1     1     2     3
2     4     5    NA

irisを使って

irisを書き込み、読みだすところまでやる。

csv形式で書き込む。read_csv()と同じ

iris[1,1] <- NA # なんとなくNAを混ぜてみた
write_delim(iris,
            path = "data/iris.csv",
            delim = ",", # カンマで指定した。つまりread_csvでも読み出せる
            na = "" # 欠損にはなにも入れない
            )

読み出す。read_delim()read_csv()の両方で出来ることを確認する。
地味に列の型を指定するcol_typeが便利。d(double)なら実数、i(integer)なら整数、という具合

read_delim("data/iris.csv", delim = ",")
# A tibble: 150 x 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl>   <chr>
 1           NA         3.5          1.4         0.2  setosa
 2          4.9         3.0          1.4         0.2  setosa
 3          4.7         3.2          1.3         0.2  setosa
 4          4.6         3.1          1.5         0.2  setosa
 5          5.0         3.6          1.4         0.2  setosa
 6          5.4         3.9          1.7         0.4  setosa
 7          4.6         3.4          1.4         0.3  setosa
 8          5.0         3.4          1.5         0.2  setosa
 9          4.4         2.9          1.4         0.2  setosa
10          4.9         3.1          1.5         0.1  setosa
# ... with 140 more rows
read_csv("data/iris.csv", col_type = "ddccc"  # 何となく後ろ3列を文字列で読み込んでみた
)
# A tibble: 150 x 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <chr>       <chr>   <chr>
 1           NA         3.5          1.4         0.2  setosa
 2          4.9         3.0          1.4         0.2  setosa
 3          4.7         3.2          1.3         0.2  setosa
 4          4.6         3.1          1.5         0.2  setosa
 5          5.0         3.6          1.4         0.2  setosa
 6          5.4         3.9          1.7         0.4  setosa
 7          4.6         3.4          1.4         0.3  setosa
 8          5.0         3.4          1.5         0.2  setosa
 9          4.4         2.9          1.4         0.2  setosa
10          4.9         3.1          1.5         0.1  setosa
# ... with 140 more rows

よくある質問

  • 区切り文字を含んだ文字列(文章みたいな)を同じセルに入れるにはどうしたらいいですか
    • quoteで区切り文字を指定し読み込む
read_csv("x,y\n1,'a,b'", # quoteで囲まれた a,b をまとめて一つのセルに入れたい
         quote = "'" # quote に ' を指定
         )
# A tibble: 1 x 2
      x     y
  <int> <chr>
1     1   a,b
  • 文字コードの問題はどうやって解決するの?
    • write_*系は常にUTF-8で書き込まれる。神の強い意志を感じる
    • エクセルで文字化けしないようにするためには、write_excel_csv()を使用するとエクセル側で勝手にUTF-8で読み込んでくれる。
    • Shift-JISなどの他のコードを読み込むときは、次ようにする
    • locale()は様々な環境を設定できる関数。 興味があったらvignette("locales")して
read_csv("data/iris.csv", locale = locale(encoding = "Shift-JIS"))
# A tibble: 150 x 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl>   <chr>
 1           NA         3.5          1.4         0.2  setosa
 2          4.9         3.0          1.4         0.2  setosa
 3          4.7         3.2          1.3         0.2  setosa
 4          4.6         3.1          1.5         0.2  setosa
 5          5.0         3.6          1.4         0.2  setosa
 6          5.4         3.9          1.7         0.4  setosa
 7          4.6         3.4          1.4         0.3  setosa
 8          5.0         3.4          1.5         0.2  setosa
 9          4.4         2.9          1.4         0.2  setosa
10          4.9         3.1          1.5         0.1  setosa
# ... with 140 more rows
  • 読み込んだデータが普通のデータフレームと違くない??
    • その通り。読み込んだirisのクラスを確認する
class(read_csv("data/iris.csv"))
[1] "tbl_df"     "tbl"        "data.frame"
  • 実は、データフレームの欠点を補うtibble(tbl)というクラスが存在する。
  • readrで読み込まれたデータは自動的にこのtibble形式で読み込まれる。
  • どこが違うのか???つづく!!

その他

その他のreadr関数

区切り文字によるファイル以外にも、固定幅ファイルを読み込むread_fwf()や Apacheファイルを読み込むread_log()などがある

その他のパッケージ

  • SPSS, Stata, SASファイルを読む用のhavenパッケージ
  • データベース用のDBIパッケージ
  • エクセルファイルを読み込む用のreadxlパッケージなどがある

Yutaka Kuroki

2018年2月26日