crossfilter.js

いろんな属性を持つデータのフィルタリング・集計をjavascript上で高速に扱えるライブラリ。

例  
ID   姓    名   性  年齢   身長   体重  ...    ←属性
00  田中  一郎  男   18   170.1   58.6
01  佐藤  二郎  男   35   168.7   73.9
02  鈴木  花子  女   21   161.0   49.3
...

「体重が50kg以上の人の身長の平均値」「男性かつ40歳以上の人数」などなどを、数万~数十万レコードでもそれなりに高速に集計できる。

crossfilterが取り扱う処理はデータの集計のみなので、可視化に関してはd3.jsなどのグラフ化ライブラリで行う。d3.jsとcrossfilter.jsを互いに連携させるdc.jsというライブラリもある。

多機能だし多く使われているのでjavascript上でデータ集計するなら学習する価値はあるが、やはりライブラリ特有の問題として、 きちんと仕様を理解しておかないと思いがけない原因によりエラーが出たりする。

以下の記述の環境

  • node.js v12.19.0
  • npm 6.14.8
  • crossfilter2 1.5.4

トラブルメモ

欠損値は非サポート

NaNやundefinedが含まれるデータは明確に非サポートと言及されている。

In particular, note that incomparable values such as NaN and undefined are not supported. In addition, care should be taken when mixing types, e.g., strings and numbers. If strings and numbers are mixed, the strings will be coerced to numbers, and hence the strings must all be coercible to number, otherwise unsupported NaN values will result.
DeepL:
特に、NaNやundefinedのような比較不可能な値はサポートされていないので注意が必要です。さらに、文字列と数値などの型を混在させる場合には注意が必要です。文字列と数値が混在している場合、文字列は数値に強制的に結合されるため、文字列はすべて数値に結合可能でなければならず、そうしないとサポートされていないNaN値が発生します。

なので、欠損値を埋めるとか、無視するとかといった機能がcrossfilter側で提供されてはおらず、与える段階で除くなり処理しておくことになる。

NaNが含まれるデータは、そのままでもdimensionを作るところまでは出来てしまうが、集計時にエラーとなる可能性がある。

例えばdimension.group()でグループ化しようとした場合、crossfilterの内部ループが永久に終わらず Out of memory となって危険。

group()に与えることの出来る関数の制約

dimension.group() では、そのdimensionにおいて同じ値を持つレコードをグループ化し、グループ毎の平均や、レコードカウントを集計できる。

また、関数を与えると、値をその関数に通した返値を基準にグループ化を行う。
ヒストグラムなんかを作るとき、20ごとにbinを作ろうとしたら dimension.group(d ⇒ Math.floor(d / 20) * 20) とかするといい。

ただし、この関数の返値は、「そのdimensionの値を昇順ソートした順に関数を通すと、返値もまた昇順で並ぶ」ようになっていないといけない?(細かな解釈は間違ってるかも)。

つまり、以下のような例は変な結果を返す。

  • 1年以上にわたる日付データから d ⇒ d.getMonth() など月をキーにグループ化(11の次に0に戻る)
  • d ⇒ -dd ⇒ d % 10 などソート順が変わるような値をキーにグループ化

もし月別の集計値が欲しければ、dimensionを作る段階で、最初から月を基準としておく。

programming/web_development/javascript/crossfilter.txt · 最終更新: 2021/01/29 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0