【问题标题】:Pig: Running two aggregation functionsPig:运行两个聚合函数
【发布时间】:2014-07-14 18:40:35
【问题描述】:

我是 Pig 新手,想运行两个聚合函数,但我不知道该怎么做。我的数据包含每行一个购买交易,其中我有一个 SKU(库存标识符)和客户为 SKU 支付的价格(价格可能会有所不同):

sku   price_paid
---   ----------
123        21.70
789        62.12
123        22.10
123        19.78
456        11.91
789        55.13

我想生成以下列表,其中包含 SKU、购买 SKU 的次数以及为 SKU 支付的平均价格。该列表应按计数降序排序。

sku      count  ave_price_paid
---  ---------  --------------
123          3           21.19
789          2           58.63 
456          1           11.91

任何帮助将不胜感激。我目前还没有走多远:

A = LOAD 'mydata.csv' USING PigStorage(',') AS (sku:chararray, price_paid:double);
B = GROUP A BY sku;

【问题讨论】:

    标签: hadoop mapreduce apache-pig


    【解决方案1】:

    聚合函数接受一袋值并产生单个值。由于您将操作的包是属于由 GROUP BY 语句创建的关系的一部分的字段,因此我将首先解释这一点。

    GROUP BY 会将给定键的所有具有相同值的记录收集到一个包中(一个包是记录的无序集合)。 关系 B 的记录包含 2 个字段:

    1. 一个键,被命名为组(例如sku
    2. 一袋收集的记录,其名称是为其分组的别名(关系名称)(例如 A)。请注意下面您的包如何“继承”与 A 相同的架构。

    让我们尝试使用 DESCRIBE 语句,它将向您显示关系的架构,例如如果你这样做:

    DESCRIBE B;
    

    输出是:

    B: {group: chararray,A: {(sku: chararray,price_paid: double)}}
    

    对应上面的解释。

    考虑到这一点,现在您可以执行以下语句:

    C = FOREACH B GENERATE group, COUNT(A) as (count:long), AVG(A.price_paid) as (avg:double);
    

    COUNT 计算一个包中的记录数,而 AVG 对作为输入提供的所有值进行平均,例如包中元组记录中的 price_paid 值(注意访问它们的方式!

    然后您执行订购:

    D = ORDER C BY count desc;
    

    完整代码如下:

    A = LOAD 'pathOfYourFile' as (sku:chararray, price_paid:double);
    B = GROUP A BY sku;
    C = FOREACH B GENERATE group, COUNT(A) as (count:long), AVG(A.price_paid) as (avg:double);
    D = ORDER C BY count desc;
    

    有关 pig 内置函数的更多信息,您可以查看 apache 参考:http://pig.apache.org/docs/r0.13.0/func.html

    【讨论】:

      【解决方案2】:

      这应该对你有用:

      C = FOREACH B GENERATE group, COUNT(A) AS count:long, AVG(A.price_paid) AS avg:double;
      D = ORDER C BY count DESC;
      

      说明:

      让我们从您已经拥有的代码开始:

      A = LOAD 'mydata.csv' USING PigStorage(',') AS (sku:chararray, price_paid:double);
      B = GROUP A BY sku;
      

      现在我们有了关系 B,它由两个字段组成:组名及其对应的包。组名只是一个组的名称,如“123”。该包将是该特定组的所有行的列表。例如:

      sku         bag
      ----       ----
      123        {{123, 21.70}, {123, 22.10}, {123,19.78}}
      

      如果您输入DESCRIBE B;,那么您应该得到以下信息:

      {group: chararray, A: {sku:chararray, price_paid:double}}
      

      在此模式中,A 是袋子,并且在袋子中可能有许多项目中,每个项目都有一个 sku 字段和 price_paid 字段。

      现在我们需要使用 Pig 强大的FOREACH...GENERATE 语句:

      C = FOREACH B GENERATE group, COUNT(A) AS count:long, AVG(A.price_paid) AS avg:double;
      

      上面这行是说对于关系 B 中的每一行,输出:

      1. 组名
      2. 组包的COUNT()——整个包的行数。使用 AS 子句,将此列命名为 'count' 并使其变长。
      3. 包中所有 price_paid 字段的AVG()。使用AS 子句,将此列命名为“avg”并将其设为双精度。

      最后:

      D = ORDER C BY count DESC;
      

      这将按“count”列的降序对关系 C 进行排序。

      【讨论】:

      • 谢谢。运行语句 B 后,'bag' 是 Pig 生成的列名吗?如果是这样,我可以用它来代替“$1”吗?
      • 如果你输入命令'DESCRIBE B;'它应该告诉你列的名称。我相信输入 DESCRIBE B 会产生以下结果: {group: chararray, A: {sku:chararray, price_paid:double}} 在这种情况下,A 是具有两个字段的包 - sku 和 price_paid。换句话说,一个组的包里有一行或多行,每行都有一个 sku 和 price_paid 字段。因此,您可以为 C 语句输入以下内容:C = FOREACH B GENERATE group, COUNT(A), AVG(A.price_paid);
      • 我将上面的答案更改为不使用美元符号语法。
      猜你喜欢
      • 1970-01-01
      • 2014-01-21
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 2021-06-16
      • 1970-01-01
      • 2013-08-13
      相关资源
      最近更新 更多