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 specialARROW:schema
key in the metadata, so that we can detect that a column was originallyDictionaryArray
.
「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 LinuxにApache Arrowをインストールするには?
正解がよくわかりません。
stable版
stable版は、AURにはarrowというパッケージがあり、yay
でインストールすることができます。
が、依存パッケージのバージョンによってビルドがエラーになったりしてちょっと苦しみました。zstd
はzstd-git
を使わないとだめでした。
$ yay -S zstd-git
しかし、Rパッケージの開発をしようと思うと結局自分でビルドする必要があるっぽいです。
GitHub版
こんな感じでインストールしました。cmake
のオプションはAURにあるarrowのPKGBUILDを盗み見て、
最後の-DOrc_SOURCE=BUNDLED
だけ、apache-orcのバージョンが低いというエラーが出たので書き加えました。