hortonworksのhadoopを触る2 (チュートリアル2:pig)
pigの使い方(ちょっと実践)
- hortonworksの「Tutorial 2: How To Process Data with Apache Pig」を行ったメモ
データの準備
元データをここからダウンロード
- http://seanlahman.com/files/database/lahman591-csv.zip
- 解凍して、 master.csv と batting.csvをuploadする
データの内容は下記の通り
野球のデータっぽい
playerID,yearID,stint,teamID,lgID,G,G_batting,AB,R,H,2B,3B,HR,RBI,SB,CS,BB,SO,IBB,HBP,SH,SF,GIDP,G_old aardsda01,2004,1,SFN,NL,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11 aardsda01,2006,1,CHN,NL,45,43,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,45 aardsda01,2007,1,CHA,AL,25,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 aardsda01,2008,1,BOS,AL,47,5,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,5 aardsda01,2009,1,SEA,AL,73,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
PigStorage
batting = load 'Batting.csv' using PigStorage(',');
- Batting.csvを読み込んで、カンマ区切りで分割する
FOREACH/GENERATE
runs = FOREACH batting GENERATE $0 as playerID, $1 as year, $8 as runs;
- 「foreach」は、入力データを1レコードずつ処理していく命令
- GENERATE はデータの列を処理するために使う
- 1列目をplayerID、2行目をyear、9行目をrunとする(射影).
- 下記のようなテーブルになる。
playerID year runs aardsda01 2004 10
GROUP
grp_data = GROUP runs by (year);
- 特定の値ごとにグループを生成する
年度ごとの全選手の値がグループ化された
(1871,{(selmafr01,1871,14),(flowedi01,1871,39),・・・)}) (1872,{(burdoja01,1872,26),(allenha01,1872,8),・・・)})
MAX
max_runs = FOREACH grp_data GENERATE group as grp,MAX(runs.runs) as max_runs;
- グループ内で最大の値を返す
- nullがある場合、無視される
・・・ここで、エラーが発生!!
- チュートリアル通りに行ったが、ここでエラーが発生した・・・。
Error executing an algebraic function
- 公式ドキュメントにあったが、どうやらrunのカラムにnumeric型以外のものが認識されていることによっておこっているらしい
- http://hortonworks.com/community/forums/topic/tutorial-2-error-2106-error-executing-an-algebraic-function/
明示的に型を指定することでエラーの回避ができる
batting = load 'Batting.csv' using PigStorage(','); runs = FOREACH batting GENERATE (chararray)$0 AS playerID, (int)$1 AS year, (int)$8 AS runs; -- DESCRIBE runs; grp_data = GROUP runs BY (year); max_runs = FOREACH grp_data GENERATE group AS grp, MAX(runs.runs) AS max_runs; -- DESCRIBE max_runs;
修正後、結果は下記のようになる
(1871,66) (1872,94) (1873,125) (1874,91)
この問題は、実際に行うときにもハマりそうだな・・・
- 年度ごとにrunが最も大きい値が抽出された
JOIN
join_max_run = JOIN max_runs by ($0, max_runs), runs by (year,runs);
- max_runsの1列目(year)とmax_runs と runsのyearとruns を複合キーとしてinnerjoinしている
- 年度ごとにもっともrunが大きい値の選手の情報を追加
結果は下記の通り
(1871,66,barnero01,1871,66) (1872,94,eggleda01,1872,94) (1873,125,barnero01,1873,125) (1874,91,mcveyca01,1874,91) (1875,115,barnero01,1875,115) (1876,126,barnero01,1876,126) (1877,68,orourji01,1877,68)
join_data = FOREACH join_max_run GENERATE $0 as year, $2 as playerID, $1 as runs;
データを整形
(1871,barnero01,66) (1872,eggleda01,94) (1873,barnero01,125) (1874,mcveyca01,91) (1875,barnero01,115)
DUMP
dump join_data;
- 格納されているデータを確認
- 特定のカラムだけの抽出はできない
最終的なスクリプト
batting = load 'Batting.csv' using PigStorage(',');
runs = FOREACH batting GENERATE
(chararray)$0 AS playerID,
(int)$1 AS year,
(int)$8 AS runs;
-- DESCRIBE runs;
grp_data = GROUP runs BY (year);
max_runs = FOREACH grp_data GENERATE
group AS grp, MAX(runs.runs) AS max_runs;
-- DESCRIBE max_runs;
join_max_run = JOIN
max_runs BY (grp, max_runs),
runs by (year, runs);
-- DESCRIBE join_max_run;
join_data = FOREACH join_max_run GENERATE
$0 as year,
$2 as playerID,
$1 as runs;
DESCRIBE join_data;
STORE join_data INTO 'baseball1';
dump join_data;