【RDB / JSON / S3】R でデータを読み込む方法を整理してみた

R で以下のデータソースからデータを読み込む方法を簡単に整理してみました。各パッケージの詳細については触れません。

  • CSV
  • TSV
  • JSON
  • XLSX
  • MySQL
  • Amazon S3
  • R Object

CSV

ファイルサイズの小さい CSV (Comma-Separated Values) であれば, utils::read.csv でも良いと思うが, サイズが大きい場合は {data.table} の fread() や {readr} の read_csv() が高速。

data.table は data.frame の多くを継承したデータ型で, バイナリサーチを用いた高速検索が特徴のひとつ。

library(data.table)

baseball <- fread("data/baseball.csv", header = TRUE)

data.table::fread の引数 に data.table = FALSE を指定すると data.frame が返る。 (デフォルトは TRUE)

readr::read_csv も高速に読み込め, さらに utils::read.csv のように文字ベクトルを factor に変換したり列名を読みにくいものに変えたりしないためデファクトスタンダードとなっている印象。また, readr::read_csv は data.frame でなく tibble を返す。(tibble は data.frame と異なり $ 指定で値でなく tibble を返す)

TSV

TSV (Tab-Separated Values) は data.table::fread や readr::read_tsv で読み込むことができる。

試しに Nginx のログフォーマットを LSTV (Labeled Tab-Separated Values) に設定して読み込んだ。

tsv <- fread("data/access.log", header = FALSE)

JSON

JSON (JavaScript Object Notation) をファイルから読み込む場合は {jsonlite}, {rjson} などがある。 {jsonlite} の方が Github の Star が多いこともあり, こちらを使ってみる。

jsonlite::fromJSON は list を返す。

library(jsonlite)

# from JSON file
data.json <- fromJSON("data/attractions.json")

補足で, 直書きしたJSON文字列を整形したい場合は {jqr} の jq() があり, 特定の位置の値を抜き取ったりもできる。

library(jqr)

# from JSON text
data.raw <- '[{"code":1,"name":"カリブの海賊"},{"code":2,"name":"ビッグサンダー・マウンテン"}]'

jq(data.raw, ".")
# [
#     {
#         "code": 1,
#         "name": "カリブの海賊"
#     },
#     {
#         "code": 2,
#         "name": "ビッグサンダー・マウンテン"
#     }
# ]

XLSX

XLSX は Excel 2007 以降のExcelフォーマット。
R で読み込むには {readxl}, {openxlsx}, {xlsx}, {XLConnect} などがある。{readxl} が高速のようだが, どの程度かは試せていない。

library(readxl)

data <- read_excel("data/disease.xlsx", sheet = 1)

CSV に変換するのが面倒な場合に使う機会があるかもしれない。
ちなみに {xlsx} はJavaを必要するが {openxlsx} は必要としない。

MySQL

R から MySQL に接続するには, {RMySQL} が良さそう。

試しに dev.mysql.com がホストしている world database を使ってみる。 world.sql を DL して, mysql に import する。

$ mysql -u root -p mysql < world.sql

world は City, Country, CountryLanguage の3つのテーブルを持っている。dbGetQuery() は SQL の応答を data.frame で返す。

library(RMySQL)

con <- dbConnect(MySQL(), host="localhost", port=25025, dbname="world",
                 user="root", password="your-password")

country <- dbGetQuery(con, "SET NAMES utf8")
country <- dbGetQuery(con, "SELECT * FROM Country")

他にも, ODBC接続の環境だと, {RODBC}, PostgreSQLだと {RPostgreSQL}, NoSQLの MongoDB なら {rmongodb} 辺りのパッケージが比較的情報が多い。

Amazon S3

S3 へのアクセスは {aws.s3} を使ってみた
まず, Sys.setenv() で S3 への認証情報を環境変数に設定する。get_bucket() でバケット内の S3 オブジェクト一覧を取得でき, get_object() で S3 オブジェクトを R の raw vector 表現として取得できる。

library(aws.s3)
library(dplyr)

Sys.setenv("AWS_ACCESS_KEY_ID" = "[ACCESS_KEY]",
           "AWS_SECRET_ACCESS_KEY" = "[SECRET_KEY]")

bucket_name <- "t2sy.example"
# # The objects in the bucket are below.
# {"name": "Alice", "age": 30, "gender": "F"}
# {"name": "Bob", "age": 25,"gender": "M"}
# {"name": "Eve", "age": 20, "gender": "F"}

objects.json <- get_bucket(bucket_name) %>%
  lapply(function(x) {
    get_object(x$Key, bucket = bucket_name) %>%
      rawToChar() %>%
      jsonlite::fromJSON()})

df <- do.call(function(...) rbind(data.frame(), ...), objects.json)
rownames(df) <- NULL
# > df
#    name age gender
# 1 Alice  30      F
# 2   Bob  25      M
# 3   Eve  20      F

R Objects

R 以外でデータを使わない場合は R のオブジェクトとして保存すると特に大きな data.frame でサイズ効率が高い。保存は base::save(), 読み込みは base::load() で行う。

# Save R Objects
save(baseball, file = "data/baseball.RData")

# Reload Saved Datasets
load("data/baseball.RData")

個人的には前処理がある程度進んだ時点で, 中間オブジェクトとして保存することが多い。

Code は GitHub に置いた。

おわりに

Rパッケージを整理すると下記のようになりました。もっと良いのがあれば教えて頂ければと思います。

  • CSV: {readr}, {data.table}
  • TSV: {readr}, {data.table}
  • JSON: {jsonlite}
  • XLSX: {readxl}
  • MySQL: {RMySQL}
  • PostgreSQL: {RPostgreSQL}
  • Amazon S3: {aws.s3}

今回紹介したデータソースからの読み込みやデータ操作については, データ分析プロセス (シリーズ Useful R 2) が詳しいです。