Pig By Pig

时间:2013-04-15 14:53:04

标签: hadoop group-by apache-pig

在PigLatin中,我想分组2次,以便选择具有2种不同规律的行。

我无法解释问题,所以这是一个例子。假设我想抓住最接近我的年龄($ my_age)并且有很多钱的人的规格。

Relation A is four columns, (name, address, zipcode, age, money)

B = GROUP A BY (address, zipcode); # group by the address

-- generate the address, the person's age ...

C = FOREACH B GENERATE group, MIN($my_age - age) AS min_age, FLATTEN(A);

D = FILTER C BY min_age == age

--Then group by as to select the richest, group by fails :

E = GROUP D BY group; or E = GROUP D BY (address, zipcode);

-- The end would work
D = FOREACH E GENERATE group, MAX(money) AS max_money, FLATTEN(A);

F = FILTER C BY max_money == money;

我试图同时过滤最近和最富有的人,但它不起作用,因为你可以拥有最年长的最富有的人。


另一个更现实的例子是:

您有需求文件:iddem,idopedem,datedem

您有以下操作文件:idope,labelope,dateope,idoftheday,infope

我想返回符合以下要求的操作: idopedem匹配ideope。

dateope必须与datedem最接近。

如果是datedem - date_ope> 0,然后我必须用max(idoftheday)选择操作,否则我必须用min(idoftheday)选择操作。

Relation A is 5 columns (idope,labelope,dateope,idoftheday,infope)
Relation B is 3 columns (iddem, idopedem, datedem)

C = JOIN A BY idope, B BY idopedem;

D = FOREACH E GENERATE iddem, idope, datedem, dateope, ABS(datedem - dateope) AS datedelta, idoftheday, infope;

E = GROUP C BY iddem;

F = FOREACH D GENERATE group, MIN(C.datedelta) AS deltamin, FLATTEN(D);

G = FILTER F BY deltamin == datedelta;

--Then I must group by another time as to select the min or max idoftheday
H = GROUP G BY group; --Does not work when dump
H = GROUP G BY iddem; --Does not work when dump

I = FOREACH H GENERATE group, (datedem - dateope >= 0 ? max(idoftheday) as idofdaysel : min(idoftheday) as idofdaysel), FLATTEN(D);

J = FILTER F BY idofdaysel == idoftheday;

DUMP J;

第二个例子中的数据(注释日期已经是Unix格式): 你有这样的需求文件:

1, 'ctr1', 1359460800000
2, 'ctr2', 1354363200000

您有以下操作文件: idope,labelope,dateope,idoftheday,infope

'ctr0','toto',1359460800000,1,'blabla0'
'ctr0','tata',1359460800000,2,'blabla1'
'ctr1','toto',1359460800000,1,'blabla2'
'ctr1','tata',1359460800000,2,'blabla3'
'ctr2','toto',1359460800000,1,'blabla4'
'ctr2','tata',1359460800000,2,'blabla5'
'ctr3','toto',1359460800000,1,'blabla6'
'ctr3','tata',1359460800000,2,'blabla7'

结果必须如下:

1, 'ctr1', 'tata',1359460800000,2,'blabla3'
2, 'ctr2', 'toto',1359460800000,1,'blabla4'

1 个答案:

答案 0 :(得分:0)

示例输入和输出将有很大帮助,但是根据您发布的内容,我认为问题不在于编写Pig脚本,而在于指定您希望完成的内容。我不清楚你为什么要分组。例如,按地址分组的目的是什么?

以下是我如何解决您的问题:

首先,设计一个优化函数,该函数将对您的数据集进行排序,反映您自己对货币与年龄的优先级。例如,为了严重惩罚大的年龄差异,但更喜欢小的钱,你可以尝试:

scored = FOREACH A GENERATE *, money / POW(1+ABS($my_age-age)/10, 2) AS score;
ordered = ORDER scored BY score DESC;
top10 = LIMIT ordered 10;

根据您的优化功能,它为您提供了10个最佳人选。

然后唯一的工作就是设计一个与你自己的判断相匹配的功能。例如,在我选择的功能中,年龄为10万美元且年龄为10岁的人会优先选择年龄为10岁(或更年轻)的350,000美元的人。但年龄在20岁或以下的年龄在50美元以上的人比年龄仅为5万美元的人更受青睐。如果其中任何一个不符合您的直觉,那么修改公式。可能一个简单的二次因子是不够的。但通过一些实验,你可以找到适合你的东西。