在Pig Group的结果中循环

时间:2013-04-03 06:38:25

标签: hadoop apache-pig

假设我有玩家ID游戏。每个id可以有多个角色名称(playerNames),我们每个名称都有一个分数。我想计算每个玩家名称的所有得分,并计算每个玩家每个玩家名称的百分比。

所以,例如:

id  playerName  playerScore
01  Test        45
01  Test2       15
02  Joe         100

会输出

id  {(playerName, playerScore, percentScore)}
01  {(Test, 45, .75), (Test2, 15, .25)}
02  {(Joe, 100, 1.0)}

我是这样做的:

data = LOAD 'someData.data' AS (id:int, playerName:chararray, playerScore:int);
grouped = GROUP data BY id;

withSummedScore = FOREACH grouped GENERATE SUM(data.playerScore) AS summedPlayerScore, FLATTEN(data);

withPercentScore = FOREACH withSummedScore GENERATE data::id AS id, data::playerName AS playerName, (playerScore/summedPlayerScore) AS percentScore;

percentScoreIdroup = GROUP withPercentScore By id;

目前,我使用2个GROUP BY语句执行此操作,我很好奇它们是否必要,或者是否有更有效的方法来执行此操作。我可以将其减少为单个GROUP BY吗?或者,有没有一种方法可以迭代元组包并将百分数增加到所有这些而不会使数据变平?

1 个答案:

答案 0 :(得分:1)

不,如果没有2 GROUP,你就无法做到这一点,原因比猪只更为根本:

  1. 要获得总分数,您需要线性通过玩家的分数。
  2. 然后,您需要对玩家的分数进行另一次线性传球来计算分数。在您知道总和之前,您可以执行此操作。
  3. 话虽如此,如果玩家的playerName s的数量很小,我会写一个UDF,它拿一袋玩家得分并输出一个每玩家名称得分的包,因为每个{{ 1}}将生成一个reducer,这个过程变得非常慢。拿着袋子的UDF也必须做那两个线性通过,但是如果袋子足够小,它就没关系了,它肯定比创建另一个减速器快一个数量级。