我找不到猪的这个看似简单问题的解决方案。
我有一张表格如下:
(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)
答案 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个参数:
关于你提出的解决方案,这很好,但是由于使用了CROSS和JOIN操作,因此使用额外的MapReduce作业会导致效率不高。
您可以在本系列中了解有关何时避免在猪中使用CROSS的问题:http://blog.mortardata.com/post/74952451884/why-did-the-pig-cross-the-join-part-4
希望它会有所帮助。