Rでデータを保存するときには、CSV形式などでテーブル1つを1ファイルで保存することが多いですが、複数の表をYAML形式で1つのファイルにまとめて保存することができます。
テーブルをYAML形式で保存する
まず、1つのテーブルの保存です。
library(tidyverse)
library(yaml)
table1 <- data.frame(a=c(1,2,3),b=c(10.3,11.6,12))
write_yaml(table1, "table1a.yaml")
保存されたファイルはテキストになっていますので、テキストエディタなどで読むことができます。
a:
- 1.0
- 2.0
- 3.0
b:
- 10.3
- 11.6
- 12.0
列単位のベクトルになっています。
行数が多くなると、行単位で保存した方がテキスト見る場合読みやすいように思います。
write_yaml(transpose(as.list(table1)), "table1b.yaml")
- a: 1.0
b: 10.3
- a: 2.0
b: 11.6
- a: 3.0
b: 12.0
ファイルからデータを読むには、後者は少し工夫がいります。
table1a <- data.frame(read_yaml("table1a.yaml"))
table1b <- map_dfr(read_yaml("table1b.yaml"), as.data.frame)
複数のテーブルを1つにまとめて保存
複数テーブルをリストとしてまとめて1つのファイルに保存できます。
table2 <- data.frame(a=c("A", "B"),b=c(3,4))
data <- list(table1_data=table1, table2_data=table2)
write_yaml(data, "table_data.yaml")
ファイルを読み込むと、保存したデータと同じテーブルのリストになります。
table.data <- read_yaml("table_data.yaml")
table1.data <- data.frame(table.data$table1_data)
table2.data <- data.frame(table.data$table2_data)
Rubyプログラムで読み書きする
YAML形式は多くのプログラミング言語でサポートされているので簡単に読み書きできます。
Rubyの例を示します。Hashクラスのデータとして読み込まれます。(keyはStringクラスになっています)
require "rover-df"
require "yaml"
# 読み込み
table1a=Rover::DataFrame.new(YAML.load_file("table1a.yaml"))
table1b=Rover::DataFrame.new(YAML.load_file("table1b.yaml"))
table_data=YAML.load_file("table_data.yaml")
table1_data=Rover::DataFrame.new(table_data["table1_data"])
table2_data=Rover::DataFrame.new(table_data["table2_data"])
# 書き込み
table_data2={"table1_data"=>table1_data.to_h, "table2_data"=>table2_data.to_h}
open("table_data2.yaml", "w"){|f| f.puts table_data2.to_yaml}
RのlistとRubyのHashはYAML形式で互換性があります。しかし、YAMLではRubyのシンボルに相当するクラスは定義されていないようで、Rとのデータのやり取りにはHashのkeyをStringクラスにしておく必要があります。
以下のように、symbolize_keysとstringify_keysでHashのキーString,Symbol間で変換できます。
require "rover-df"
require "yaml"
require "active_support"
require "active_support/core_ext"
# 読み込み
table1a=Rover::DataFrame.new(YAML.load_file("table1a.yaml").symbolize_keys)
table1b=Rover::DataFrame.new(YAML.load_file("table1b.yaml").map(&:symbolize_keys))
table_data=YAML.load_file("table_data.yaml")
table1_data=Rover::DataFrame.new(table_data["table1_data"].symbolize_keys)
table2_data=Rover::DataFrame.new(table_data["table2_data"].symbolize_keys)
# 書き込み
table_data2={"table1_data"=>table1_data.to_h.stringify_keys, "table2_data"=>table2_data.to_h.stringify_keys}
open("table_data2.yaml", "w"){|f| f.puts table_data2.to_yaml}