5

我是 Pig 的新手,并试图正确实现一个有点通用的算法,在该算法中,我需要配对一组记录中的每个匹配记录。为了将问题提炼成最简单的形式并避免讨论一些特定于业务的敏感性,这里有一个模拟问题:

假设我有一个代表大学课程和参加这些课程的学生的数据集:

Philosophy,John
English,Mary
English,Sue
History,Jack
Philosophy,David
English,Mark
English,Larry

我想配对上同一门课的学生之间的每一个关联;所以输出将包括这个,显示四个“英语”行爆炸成六个关联:

Philosphy   John,David
English    Mary,Sue
English    Mary,Mark
English    Mary,Larry
English    Sue,Mark
English    Sue,Larry
English    Mark,Larry

本页: http: //ofps.oreilly.com/titles/9781449302641/advanced_pig_latin.html是指使用 flatten() 来实现叉积。我已经尝试了几种方法并对此进行了广泛的研究,并会发布我的尝试,但老实说,我正在摇摆不定,我认为这只会让读者感到困惑并且不会提供任何价值。但这是样板:

s = load 'classes' using PigStorage(',') as (class:chararray, student:chararray);
grp = group s by class;
...

(我相信我面临的问题与需要多个袋子而不是多个字段的展平有关,而且我不知道如何让我的分组生成多个袋子......)

感谢您的任何帮助!

4

3 回答 3

6

您可以使用LinkedIn 的Datafu 项目中的UnorderedPairs UDF 。从这里下载包并发出以下命令(在 Pig v0.10.0 上测试):

register '/home/user/datafu/dist/datafu-0.0.4.jar'
define UnorderedPairs datafu.pig.bags.UnorderedPairs();
A = load 'classes' using PigStorage(',') as (class:chararray, student:chararray);
B = GROUP A BY class;
C = FOREACH B GENERATE group, FLATTEN(UnorderedPairs(A.student));

当进一步展平结果时:

D = FOREACH C generate FLATTEN($0) as (class:chararray), 
      FLATTEN($1) as (student1:chararray), FLATTEN($2) as (student2:chararray);

你最终会得到想要的结果:

dump D;

(English,Mary,Sue)
(English,Mary,Mark)
(English,Mary,Larry)
(English,Sue,Mark)
(English,Sue,Larry)
(English,Mark,Larry)
(Philosophy,John,David)
于 2012-12-02T23:06:58.973 回答
1

这可以通过自连接和一些简单的过滤来完成。

classes1 = load 'classes' using PigStorage(',') as (class:chararray, student:chararray);
classes2 = load 'classes' using PigStorage(',') as (class:chararray, student:chararray);
joined = JOIN classes1 BY class, classes2 BY class;
filtered = FILTER joined BY classes1.student < classes2.student;
pairs = FOREACH filtered GENERATE classes1.student AS student1, classes2.student AS student2;

请注意,按 student1 < student2 过滤可以获得唯一对。

于 2012-12-03T19:26:58.013 回答
1

我对此有两种方法。我已经有一段时间没有尝试过,所以请跟进并让我们知道它们是否运作良好。


第一种方法是自联接

s1 = load 'classes' using PigStorage(',') as (class:chararray, student:chararray);
s2 = load 'classes' using PigStorage(',') as (class:chararray, student:chararray);
b = JOIN s1 BY class, s2 BY class;
...

这样做的缺点是您必须加载数据两次。有一些关于为什么这很糟糕的讨论,但这只是你必须如何去做。


另一种选择是在 a之后使用CROSS嵌套:FOREACHGROUP

注意:我完全不确定这是否可行,或者我的语法是否正确(我现在不在可以测试的环境中)。也许有人可以证实。

B = GROUP s BY class;
C = FOREACH B {                          
   DA = CROSS s, s;                       
   GENERATE FLATTEN(DA);
}
于 2012-12-02T14:59:29.950 回答