Apache ArrowのRパッケージでfactorを含んだデータもParquetファイルに読み書きできるようになりました

1ヶ月前に、「Apache ArrowでParquetを読み書きするときfactorを扱う方法がよくわからない」みたいなことをゴニョゴニョ書きましたが、

直りました。

少しだけ解説しておくと、実はApache Parquetには直接「カテゴリ値」に当たるものはありません。が、Dictionary encodingという圧縮のための技術を援用してカテゴリ値を表現することができます。

Dictionary encoding is a compression strategy in Parquet, and there is no formal “dictionary” or “categorical” type. (Faster C++ Apache Parquet performance on dictionary-encoded string data coming in Apache Arrow 0.15 | Apache Arrow)

それを「メタデータARROW:schemaというキーを書いてあったらカテゴリ値って意味にしようぜ」というオレオレ規約で実現しているのが次のpull requestです。

Add ArrowWriterProperties::store_schema() option which stores the Arrow schema used to create a Parquet file in a special ARROW:schema key in the metadata, so that we can detect that a column was originally DictionaryArray.

「ParquetはCSVと違って仕様がきっちり決まっているので安心!」と宣伝してきた身としては、こういう独自拡張でなんとかしちゃうのは若干もやもやしなくもないんですが、まあ今は忘れましょう。 とにかく、Apache ArrowでParquetを読み書きすればfactorは扱えるようになりました。

なんですが、扱えるようになったはずなのになぜかRでは動かない、という状態になっていたのを直したのがこのPRでした。

今やfactorやorderedの読み書きも自由自在です。前回のブログでは普通にwrite_parquet()してread_parquet()するとcharacterに化けてしまっていましたが、 GitHub版を使うとこの通りです。リリースが待ち遠しいですね。

library(arrow, warn.conflicts = FALSE)

x <- factor("a", levels = c("b", "a", "C", "A"))
y <- factor("a", levels = c("b", "a", "C", "A"), ordered = TRUE)

d <- tibble::tibble(x = x, y = y)
d
#> # A tibble: 1 x 2
#>   x     y    
#>   <fct> <ord>
#> 1 a     a

tmp <- tempfile()

write_parquet(d, tmp)
read_parquet(tmp)
#> # A tibble: 1 x 2
#>   x     y    
#>   <fct> <ord>
#> 1 a     a

Created on 2020-01-08 by the reprex package (v0.3.0)

おまけ: Arch LinuxApache Arrowをインストールするには?

正解がよくわかりません。

stable版

stable版は、AURにはarrowというパッケージがあり、yayでインストールすることができます。 が、依存パッケージのバージョンによってビルドがエラーになったりしてちょっと苦しみました。zstdzstd-gitを使わないとだめでした。

$ yay -S zstd-git

しかし、Rパッケージの開発をしようと思うと結局自分でビルドする必要があるっぽいです。

GitHub

こんな感じでインストールしました。cmakeのオプションはAURにあるarrowのPKGBUILDを盗み見て、 最後の-DOrc_SOURCE=BUNDLEDだけ、apache-orcのバージョンが低いというエラーが出たので書き加えました。