在Pig中向表中添加行

时间:2015-05-19 16:47:45

标签: apache-pig

我找不到猪的这个看似简单问题的解决方案。

我有一张表格如下:

(USA, "big",somevalue1)
(USA, "rich",somevalue2)
(RU, "big",somevalue3)
(BR, "rich",somevalue4)
(BR, "rich",somevalue5)

作为我想要的输出

(USA, "big",somevalue1)
(USA, "rich",somevalue2)
(RU, "big",somevalue3)
(RU, "rich",0)
(BR, "rich",somevalue4)
(BR, "rich",somevalue5)
(BR, "big",0)

即添加行,以便每个国家/地区共享与第二列相同的“信息”,即使它意味着填充零未知值。

修改

这是我提出的解决方案

USA "big"   1
USA "rich"  2
RU  "big"   3
BR  "rich"  4
BR  "rich"  5

(输入example.txt)

A = LOAD 'example.txt' USING PigStorage('\t') AS (cty: chararray, prop:chararray, value: int);
B = FOREACH A GENERATE cty;
B = DISTINCT B;
C = FOREACH A GENERATE prop;
C = DISTINCT C;
D = CROSS B, C;

X = JOIN D BY (cty,prop) LEFT, A BY (cty,prop) using 'replicated';
K = FOREACH X GENERATE 
                B::cty AS cty,
                C::prop AS prop,
                (value is NULL ? 0 : value);
DUMP K;

按预期给出:

(USA,"rich",2)
(USA,"big",1)
(RU,"rich",0)
(RU,"big",3)
(BR,"rich",4)
(BR,"rich",5)
(BR,"big",0)

1 个答案:

答案 0 :(得分:2)

我认为最简单的方法是按照第一个字段进行分组,然后再将foreach组分组,将相关的包发送到您自己的UDF中,该UDF将遍历包中的元组,并将返回现有的新包元组+默认元组(如果需要)。

为了创建第二个字段所需值的列表(" utility_bag"),您可以使用distinct和group by ALL。

以下是您的脚本的外观:

input_data = LOAD 'input.csv' USING PigStorage('\t') 
               AS (country:chararray, f2:chararray, somevalue:chararray);

only_second_field = FOREACH input_data GENERATE f2;
distinct_list = DISTINCT only_second_field;
utility_bag = GROUP distinct_list ALL;

grouped = FOREACH (GROUP input_data BY country) 
     GENERATE group, CustomUDF(input_data, utility_bag.distinct_list) AS enhancedBag;

result = FOREACH grouped GENERATE flatten(enhancedBag);

您的自定义UDF应该有2个参数:

  1. 用原始架构包装:{(country:chararray,f2:chararray,somevalue:chararray)}
  2. 包装图案:{(f2:chararray)}
    例如:{(大),(丰富),(孤独)}
    • 您可以稍微玩一下袋子以消除元组并仅保留值。
  3. 关于你提出的解决方案,这很好,但是由于使用了CROSS和JOIN操作,因此使用额外的MapReduce作业会导致效率不高。

    您可以在本系列中了解有关何时避免在猪中使用CROSS的问题:http://blog.mortardata.com/post/74952451884/why-did-the-pig-cross-the-join-part-4

    希望它会有所帮助。