apache drill で日本語を扱ってみよう + オープンデータ解析

26
© 2014 MapR Technologies 1 © 2014 MapR Technologies Apache Drill ででででででででででで + ででででででででで マママママ マママママママママママ マママママママママ ママ ママ 2015/11/12

Upload: mapr-technologies-japan

Post on 13-Feb-2017

1.172 views

Category:

Data & Analytics


6 download

TRANSCRIPT

Page 1: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 1© 2014 MapR Technologies

Apache Drill で日本語を扱ってみよう + オープンデータ解析

マプアール・テクノロジーズ株式会社セールスエンジニア

梅川 真人

2015/11/12

Page 2: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 2

自己紹介• 梅川 真人 ( ウメカワマサト )• MapR Technologiesセールスエンジニア• 2015/5 に MapR にそれまでは SIer にいたが MapR に惚れてしまい転職• 趣味は YOGA 、でも最近さぼりぎみ。。

Page 3: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 3© 2014 MapR Technologies

Apache Drill で日本語を扱う時の注意点

Page 4: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 4

ゆるい日本語のデータ

No タイトル 県名1 くまモン 熊本2 ふなっしー 船橋3 せんとくん 奈良

ファイル名 : yuru.csv

Page 5: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 5

ロケール (1)

$ echo $LANGen_US.UTF-8$ sqlline0: jdbc:drill:zk=drill01:5181> select * from dfs.`/tmp/yuru.csv`;+---------------------+| columns |+---------------------+| ["1","????","??"] || ["2","?????","??"] || ["3","?????","??"] |+---------------------+3 rows selected (0.159 seconds)

ロケールが en_US.UTF-8 だと文字化けする

Page 6: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 6

ロケール (2)

$ echo $LANGja_JP.UTF-8$ sqlline0: jdbc:drill:zk=drill01:5181> select * from dfs.`/tmp/yuru.csv`;+---------------------+| columns |+---------------------+| ["1"," くまモン "," 熊本 "] || ["2"," ふなっしー "," 船橋 "] || ["3"," せんとくん "," 奈良 "] |+---------------------+3 rows selected (0.159 seconds)

Ja_JP.UTF-8 にすれば文字化けせずに表示される

Page 7: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 7

文字列リテラルのエラー

0: jdbc:drill:> select. . . . . . . > columns[0] 番号 ,. . . . . . . > columns[1] 名前 ,. . . . . . . > columns[2] 住所. . . . . . . > from dfs.`/tmp/yuru.csv`. . . . . . . > where columns[2] = ' 熊本’ ;Error: SYSTEM ERROR: CalciteException: Failed to encode ‘ 熊本’ in character set ‘ISO-8859-1’

[Error Id: 98a5ba50-81a6-4718-a274-a2b784d7d7aa on drill02:31010] (state=,code=0)

デフォルトだとエラーが・・

Page 8: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 8

文字列リテラルの対策

Apache Calcite - SQL Language http://calcite.incubator.apache.org/docs/reference.html

Drill は SQL パーサの部分に Apache Calcite を利用しているため、 Calcite のドキュメントを見てみましょう。

データ型 説明 範囲と例CHAR(n)CHARACTER(n)

Fixed-width character string

Hello’, ‘’ (空文字 ), _latin1’Hello’, n’Hello’, _UTF16’Hello’, ‘Hello’ ‘there’ (複数パートに分割されたリテラル )

Page 9: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 9

文字列リテラルの対策済みクエリ

0: jdbc:drill:zk=local> SELECT. . . . . . . . . . . > COLUMNS[0] 番号 ,. . . . . . . . . . . > COLUMNS[1] 名前 ,. . . . . . . . . . . > COLUMNS[2] 住所. . . . . . . . . . . > FROM dfs.`/tmp/test.csv`. . . . . . . . . . . > WHERE COLUMNS[2] = _UTF16' 熊本 ';+-----+--------+-----+| 番号 | 名前 | 住所 |+-----+--------+-----+| 1 | くまモン | 熊本 |+-----+--------+-----+1 rows selected (1.543 seconds)

_UTF16 をつけてみるとうまくいきました

Page 10: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 10

drill1.0 での 恒久的な対応

/** * The string property "saffron.default.charset" is the name of the default * character set. The default is "ISO-8859-1". It is used in * {@link org.apache.calcite.sql.validate.SqlValidator}.*/ public final StringProperty defaultCharset = new StringProperty(this, "saffron.default.charset", "ISO-8859-1");

毎回 _UTF16 をつけるのは面倒なのでデフォルトにできないか調べてみる

Page 11: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 11

drill1.0 での恒久的な対応

$ vi apache-drill-1.-.0/conf/drill-env.shexport DRILL_SHELL_JAVA_OPTS="-Dsaffron.default.charset=UTF-16LE"

「 saffron.default.charset 」というプロパティに UTF-16 を指定すればよさそうな感じです。これを記載するのは、設定ファイル drill-env.sh の中の環境変数DRILL_SHELL_JAVA_OPTS の設定をします。文字セット名は、いろいろ試したところ、「 UTF-16LE 」である必要があるようです。

Page 12: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 12

まとめ ロケールは “ ja_JP.UTF-8” に 文字列リテラルに _UTF16 をつける Apache-drill-1.0.0/conf/drill-env.sh なら

export DRILL_SHELL_JAVA_OPTS=“-Dsaffron.default.charset=UTF-16LE”を追記

Page 13: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 13© 2014 MapR Technologies

オープンデータから 23 区の人口増減率を調べよう

Page 14: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 14

データ取得元

政府統計の総合窓口 (e-Stat)

URL: http://www.e-stat.go.jp/api/

使用したデータ : 国勢調査 ( 平成 22 年度 )

政府統計コード : 00200521

API を使うにはサイト上から利用登録をしてアプリケーション ID を取得

Page 15: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 15

データを取得してみる

$ curl -o stats_list.json "http://api.e-stat.go.jp/rest/2.0/app/json/getStatsList?appId=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&surveyYears=2010&statsCode=00200521"

国勢調査の政府統計コード 自分のアプリケーション ID

Page 16: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 16

取得したデータを見てみる

0: jdbc:drill:zk=local> SELECT * FROM dfs.`/tmp/stats_list.json` t;+--------------------+| GET_STATS_LIST |+--------------------+{“RESULT”:{“STATUS”:0,“ERROR_MSG”:“ 正常に終了しました。” ,“DATE”:“2015-05-21T19:01:17.540+09:00”},“PARAMETER”:{“LANG”:“J”,“SURVEY_YEARS”:2010,“STATS_CODE”:“0 |+----------------+1 row selected (0.955 seconds)

Page 17: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 17

JSON データを見てみる{ "GET_STATS_LIST":{ "RESULT":{ ← 取得結果のステータス情報 “STATUS”:0, “ERROR_MSG”:"\u6B63\u5E38\u306B\u7D42\u4E86\u3057\u307E\u3057\u305F\u3002", "DATE":"2015-05-21T19:01:17.540+09:00" }, "PARAMETER":{ ← 取得時に指定したパラメータ "LANG":"J", "SURVEY_YEARS":2010, "STATS_CODE":"00200521", "DATA_FORMAT":"J" }, “DATALIST_INF”:{ ← 統計表のリストデータ本体 "NUMBER":356, “RESULT” INF”:{ "FROM_NUMBER":1, "TO_NUMBER":356 }, “TABLE_INF”:[ ← 統計表のリスト {"@id":"0003033021",...}, {"@id":"0003033022",...}, ... ] } }}

Page 18: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 18

KVGEN() と FLATTEN() 関数

KVGEN() 関数 :< キー >:< 値 >,< キー >:< 値 >,...

の並びを

[ {"key":< キー >,"value":< 値 >}, {"key":< キー >,"value":< 値 >}, ...]に分解

Apache Drill 特有の関数。 FLATTEN() 関数は配列をレコードに展開。ここで「 GET_STATS_LIST 」に対して KVGEN() 関数と FLATTEN() 関数を使うことで、一つ下の階層のキーと値の組がレコードとして展開されます。

Page 19: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 19

KVGEN() と FLATTEN() 関数で分解する0: jdbc:drill:zk=local> SELECT FLATTEN(KVGEN(t.GET_STATS_LIST)) FROM dfs.`/tmp/stats_list.json` t;+----------------------------------------------------------------------------------------------------------------------+| EXPR$0 |+----------------------------------------------------------------------------------------------------------------------+| {“key”:“RESULT”,“value”:{“STATUS”:0,“ERROR_MSG”:“ 正常に終了しました。” ,“DATE”:“2015-05-21T19:01:17.540+09:00”,“RESULT_INF”:{},“TA ||{”key“:”PARAMETER“,”value“:{”LANG“:”J“,”SURVEY_YEARS“:2010,”STATS_CODE“:”00200521“,”DATA_FORMAT“:”J“,”RESULT_INF“:{},”TABLE_INF“:[]}} ||{”key“:”DATALIST_INF“,”value“:{”NUMBER“:356,”RESULT_INF“:{”FROM_NUMBER“:1,”TO_NUMBER“:356},”TABLE_INF“:[{”@id“:”0003033021“,”STAT_ |+---------------------------------------------------------------------------------------------------------------------+3 rows selected (0.452 seconds)

Page 20: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 20

統計表 ID を取得する0: jdbc:drill:> SELECT. . . . . . . > d.table_inf.`@id`,. . . . . . . > d.table_inf.TITLE.$. . . . . . . > FROM (. . . . . . . > SELECT FLATTEN(t.GET_STATS_LIST.DATALIST_INF.TABLE_INF) table_inf. . . . . . . > FROM dfs.`/tmp/stats_list.json` t. . . . . . . > ) d. . . . . . . > WHERE d.TABLE_INF.TITLE.$ LIKE '% 人口増減 %';+-------------+-----------------------------------------------------------------+| EXPR$0 | EXPR$1 |+-------------+-----------------------------------------------------------------+| 0003038586 | 人口,人口増減,面積及び人口密度 全国,市部・郡部,都道府県,市部・郡部,支庁,郡計,市区町村・旧市町村,全域・人口集中地区 |+-------------+-----------------------------------------------------------------+1 row selected (1.465 seconds)

Page 21: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 21

地域名ビューの作成

0: jdbc:drill:zk=local> CREATE VIEW dfs.tmp.`area_info` AS SELECT. . . . . . . . . . . > t.data.`@code` code,. . . . . . . . . . . > t.data.`@name` name,. . . . . . . . . . . > t.data.`@level` level,. . . . . . . . . . . > t.data.`@parentCode` parent. . . . . . . . . . . > FROM (. . . . . . . . . . . > SELECT. . . . . . . . . . . > FLATTEN(f.GET_STATS_DATA.STATISTICAL_DATA.CLASS_INF.CLASS_OBJ[2].CLASS) data. . . . . . . . . . . > FROM. . . . . . . . . . . > dfs.`/tmp/stats_data_modified.json` f. . . . . . . . . . . > ) t;

データを SQL で扱いやすくするために、ビューとして定義してみましょう。 ここでは地域名を取り出すためのビューと、統計データを取り出すためのビューを定義します。

Page 22: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 22

統計データビューの作成

0: jdbc:drill:zk=local> CREATE VIEW dfs.tmp.`stats_data` AS SELECT. . . . . . . . . . . > t.data.`@tab` tab,. . . . . . . . . . . > t.data.`@cat01` did,. . . . . . . . . . . > t.data.`@area` area,. . . . . . . . . . . > t.data.$ val. . . . . . . . . . . > FROM (. . . . . . . . . . . > SELECT. . . . . . . . . . . > FLATTEN(f.GET_STATS_DATA.STATISTICAL_DATA.DATA_INF.`VALUE`) data. . . . . . . . . . . > FROM. . . . . . . . . . . > dfs.`/tmp/stats_data_modified.json` f. . . . . . . . . . . > ) t;

Page 23: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 23

地域名ビュー

0: jdbc:drill:zk=local> SELECT * FROM dfs.tmp.`area_info` LIMIT 10;+--------+--------+--------+---------+| code | name | level | parent |+--------+--------+--------+---------+| 00000 | 全国 | 1 | null || 00001 | 全国市部 | 1 | null || 00002 | 全国郡部 | 1 | null || 01000 | 北海道 | 2 | 00000 || 01001 | 北海道市部 | 3 | 01000 || 01002 | 北海道郡部 | 3 | 01000 || 01100 | 札幌市 | 3 | 01000 || 01101 | 中央区 | 4 | 01100 || 01102 | 北区 | 4 | 01100 || 01103 | 東区 | 4 | 01100 |+--------+--------+--------+---------+10 rows selected (11.902 seconds)

Page 24: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 24

統計データビュー0: jdbc:drill:zk=local> SELECT * FROM dfs.tmp.`stats_data` LIMIT 10;+------+--------+--------+------------+| tab | did | area | val |+------+--------+--------+------------+| 020 | 00710 | 00000 | 128057352 || 020 | 00710 | 00001 | 116156631 || 020 | 00710 | 00002 | 11900721 || 020 | 00710 | 01000 | 5506419 || 020 | 00710 | 01001 | 4449360 || 020 | 00710 | 01002 | 1057059 || 020 | 00710 | 01100 | 1913545 || 020 | 00710 | 01101 | 220189 || 020 | 00710 | 01102 | 278781 || 020 | 00710 | 01103 | 255873 |+------+--------+--------+------------+10 rows selected (87.308 seconds)

Page 25: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 25

23 区の人口増減率0: jdbc:drill:> SELECT a.name 地域 , b.val 人口 , c.val 増減率. . . . . . . > FROM (SELECT * FROM dfs.tmp.`area_info` t . . . . . . . > WHERE t.parent = '13100') a. . . . . . . > JOIN dfs.tmp.`stats_data` b. . . . . . . > ON a.code = b.area AND b.tab = '020' AND. . . . . . . > b.did = '00710’. . . . . . . > JOIN dfs.tmp.`stats_data` c. . . . . . . > ON a.code = c.area AND c.tab = '102' AND. . . . . . . > c.did = '00710' AND c.val <> '-’. . . . . . . > ORDER BY CAST(c.val AS DOUBLE) DESC;+-------+---------+-----------+| 地域 | 人口 | 増減率 |+-------+---------+-----------+| 中央区 | 122762 | 24.7594 || 豊島区 | 284678 | 13.60536 || 千代田区 | 47115 | 12.77467 || 港区 | 205131 | 10.36796 || 江東区 | 460819 | 9.49851 || 足立区 | 683426 | 9.38194 |.| 板橋区 | 535824 | 2.43575 || 目黒区 | 268330 | 1.61552 || 北区 | 335544 | 1.55321 || 中野区 | 314750 | 1.32732 || 渋谷区 | 204492 | 0.56951 |+-------+---------+-----------+23 rows selected (547.958 seconds)

Page 26: Apache Drill で日本語を扱ってみよう + オープンデータ解析

© 2014 MapR Technologies 26

Q & A@mapr_japan maprjapan

[email protected]

お問い合わせはこちらまで

MapR

maprtech

mapr-technologies

オープンデータの詳細な手順は @nagix のブログもご覧下さいhttp://nagix.hatenablog.com