Pig - 如何从列表中仅选择一些值(不仅仅是简单的不同)?

时间:2014-01-20 11:48:54

标签: hadoop tuples apache-pig

假设我有intput_file.txt(user_id,event_code,event_date):

1,a,1
1,b,2
2,a,3
2,b,4
2,b,5
2,b,6
2,c,7
2,b,8
你可以看到

,user_id = 2,有这样的事件:abbbcb
我想得到这样的结果:

1,{(a,1),(b,2)}
2,{(a,2),(b,6),(c,7),(b,8)}

因此,当我们使用相同代码的事件很少时,我只想采用最后一个事件。

请你分享一下提示吗?

此致 的Pawel

2 个答案:

答案 0 :(得分:0)

您要描述的主要内容是GROUP BY的作用。

在这种情况下:

B = GROUP A BY user_id;

通过user_id一起获取您的记录。您的数据现在将如下所示:

1,{(a,1),(b,2)}
2,{(a,2),(b,6),(c,7),(b,8)}

你说你只想要最后一个(我假设你是指具有最大event_date的那个)。为此,您可以使用FOREACH进行嵌套ORDER BY按日期排序,然后使用LIMIT进行第一次排序。请注意,当存在关联时,这会有任意行为。

C = FOREACH B {                          
   DA = ORDER A BY event_date DESC;                
   DB = LIMIT DA 1;                         
   GENERATE FLATTEN(group), FLATTEN(DB.event_code), FLATTEN(DB.event_date);
}

您的数据现在应如下所示:

1,b,2
2,b,8

另一种选择是使用UDF在GROUP BY给出的组上写一些自定义行为:

B = GROUP A BY user_id;
C = FOREACH B GENERATE YourUDFThatYouBuilt(group, A);

在那个UDF中你可以编写你想要的任何自定义行为(在这种情况下返回具有最大日期的元组)

答案 1 :(得分:0)

您似乎可以使用DistinctBy中的Apache DataFu UDF来实现此目的。给定一个包,这个UDF返回为给定字段找到的第一个实例。在您的情况下,您关心的字段是event_code。但是我们必须颠倒顺序,因为你实际上想要最后一个实例。

虽然有一个澄清。如果我错了,请纠正我,但我认为预期的输出是:

1,{(a,1),(b,2)}
2,{(a,3),(b,6),(c,7),(b,8)}

也就是说,成员2发生(a,3)事件。成员1发生(a,2)事件。

以下是您可以这样做的方法:

-- pass in 1 because we want distinct by event code (position 1)
define DistinctBy datafu.pig.bags.DistinctBy('1');

FOREACH (GROUP A BY user_id) {
  -- reverse so we can take the last event code occurrence
  A_reversed = ORDER A BY event_date DESC;

  -- use DistinctBy to get the first tuple having an occurrence of a field value
  A_distinct_by_code = DistinctBy(A_reversed);

  -- put back in order again
  A_ordered = ORDER A_distinct_by_code BY event_date ASC;

  GENERATE group as user_id, A_ordered.(event_code,event_date);
}