Hadoop 如何选择具有最小值的记录

Hadoop 如何选择具有最小值的记录,hadoop,apache-pig,Hadoop,Apache Pig,我有时间戳样本,我正在用Pig处理它们。我想找出每天样本的最小值和最小值出现的时间。所以我需要选择包含最小值样本的记录 为了简单起见,下面我将在两个字段中表示时间,第一个字段是日,第二个字段是日内的“时间” 1,1,4.5 1,2,3.4 1,5,5.6 要找到最小值,请执行以下工作: samples = LOAD 'testdata' USING PigStorage(',') AS (day:int, time:int, samp:float); g = GROUP samples BY

我有时间戳样本,我正在用Pig处理它们。我想找出每天样本的最小值和最小值出现的时间。所以我需要选择包含最小值样本的记录

为了简单起见,下面我将在两个字段中表示时间,第一个字段是日,第二个字段是日内的“时间”

1,1,4.5
1,2,3.4
1,5,5.6
要找到最小值,请执行以下工作:

samples = LOAD 'testdata' USING PigStorage(',') AS (day:int, time:int, samp:float);
g = GROUP samples BY day;
dailyminima = FOREACH g GENERATE group as day, MIN(samples.samp) as samp;
但是我失去了最小值发生的准确时间。我希望我可以使用嵌套表达式。我尝试了以下方法:

dailyminima = FOREACH g {
  minsample = MIN(samples.samp);
  mintuple = FILTER samples BY samp == minsample;
  GENERATE group as day, mintuple.time, mintuple.samp;
};
但我收到了错误信息:

2012-11-12 12:08:40,458 [main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1000: 
<line 5, column 29> Invalid field reference. Referenced field [samp] does not exist in schema: .
Details at logfile: /home/hadoop/pig_1352722092997.log
并确实产生了一个合理的结果:

(1,{(2)},{(3.4)})
写这篇文章时,我想到了使用一个单独的连接:

dailyminima = FOREACH g GENERATE group as day, MIN(samples.samp) as minsamp;
dailyminima = JOIN samples BY (day, samp), dailyminima BY (day, minsamp);
这是可行的,但结果(在实际情况中)是两个大数据集的连接,而不是搜索一天的值,这似乎不健康

在真实的情况下,我实际上想找到最大和最小以及相关的时间。我希望嵌套表达式方法能够让我同时完成这两项工作


请提供解决方法的建议。

感谢alexeipab提供的链接

一种工作解决方案(找到最小值和最大值以及相关时间)是:


另一种方法是使用PiggyBank,这个UDF实现累加器和代数,非常有效,它的优点是它不会对整个关系排序,并且只在内存中保留(潜在的)min

您的代码如下所示:

DEFINE TupleByNthField org.apache.pig.piggybank.evaluation.ExtremalTupleByNthField('3', 'min');

samples = LOAD 'testdata' USING PigStorage(',') AS (day:int, time:int, samp:float);

g = GROUP samples BY day;   

bagged = FOREACH g GENERATE TupleByNthField(samples);

flattened = FOREACH bagged GENERATE FLATTEN($0);

min_result = FOREACH flattened GENERATE $1 .. ;

请记住,我们基于samp字段进行排序的事实是在DEFINE语句中通过将3作为第一个参数来定义的。

您可以使用FOREACH中嵌套的ORDER和LIMIT。请看类似的问题,谢谢alexeipab——这引导我找到了一个有效的解决方案,在本例中是一个很好的解决方案。我很快会补充回答。我仍然想理解为什么MIN和FILTER的组合不起作用,为什么FILTER在没有MIN的情况下起作用,但在首次应用MIN时失败。
dailyminima = FOREACH g {
  minsamples = ORDER samples BY samp;
  minsample = LIMIT minsamples 1;
  maxsamples = ORDER samples BY samp DESC;
  maxsample = LIMIT maxsamples 1;
  GENERATE group as day, FLATTEN(minsample), FLATTEN(maxsample);
};
DEFINE TupleByNthField org.apache.pig.piggybank.evaluation.ExtremalTupleByNthField('3', 'min');

samples = LOAD 'testdata' USING PigStorage(',') AS (day:int, time:int, samp:float);

g = GROUP samples BY day;   

bagged = FOREACH g GENERATE TupleByNthField(samples);

flattened = FOREACH bagged GENERATE FLATTEN($0);

min_result = FOREACH flattened GENERATE $1 .. ;