假设我在HDFS上有以下平面文件(让我们称之为key_value):
1,1,Name,Jack
1,1,Title,Junior Accountant
1,1,Department,Finance
1,1,Supervisor,John
2,1,Title,Vice President
2,1,Name,Ron
2,1,Department,Billing
以下是我正在寻找的输出:
(1,1,Department,Finance,Name,Jack,Supervisor,John,Title,Junior Accountant)
(2,1,Department,Billing,Name,Ron,,,Title,Vice President)
换句话说,前两列形成唯一标识符(类似于db术语中的复合键),对于此标识符的给定值,我们希望输出中有一行(即最后两列 - 实际上是键值对 - 只要标识符相同,就会压缩到同一行上。另请注意第二行中的空值,以便在唯一标识符为(2,1)时为Supervisor部件添加占位符。
为此,我开始整理这个猪脚本:
data = LOAD 'key_value' USING PigStorage(',') as (i1:int, i2:int, key:chararray, value:chararray);
data_group = GROUP data by (i1, i2);
expected = FOREACH data_group {
sorted = ORDER data BY key, value;
GENERATE FLATTEN(BagToTuple(sorted));
};
dump expected;
上面的脚本给出了以下输出:
(1,1,Department,Finance,1,1,Name,Jack,1,1,Supervisor,John,1,1,Title,Junior Accountant)
(2,1,Department,Billing,2,1,Name,Ron,2,1,Title,Vice President)
请注意,缺少主管的空位占位符未在第二条记录中表示(预期)。如果我可以将那些空值放到位,那么看起来只是另一个投影来摆脱冗余列(前两个被复制多次 - 每个键值对一次)。
如果没有使用UDF,有没有办法在猪身上使用内置函数来实现这一目标?
更新:正如WinnieNicklaus正确指出的那样,输出中的名称是多余的。因此输出可以压缩为:
(1,1,Finance,Jack,John,Junior Accountant)
(2,1,Billing,Ron,,Vice President)
答案 0 :(得分:1)
首先,我要指出,如果对于大多数行,大多数列都没有填写,那么IMO将使用更好的解决方案。内置的TOMAP
UDF与a custom UDF to combine maps结合使您可以执行此操作。
我确信有一种方法可以通过计算所有可能键的列表来解决您的原始问题,使用空值将其展开,然后丢弃也存在非空值的实例...但这样做会涉及很多MR周期,非常难看的代码,我怀疑并不比以其他方式组织你的数据更好。
您还可以编写一个UDF来获取一个键/值对,另一个包包所有可能的键,并生成您正在寻找的元组。这将更清晰,更简单。