我有时间戳样本,我正在使用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
如果我将minsample设置为常量,则不会抱怨:
dailyminima = FOREACH g {
minsample = 3.4F;
mintuple = FILTER samples BY samp == minsample;
GENERATE group as day, mintuple.time, mintuple.samp;
};
确实产生了明智的结果:
(1,{(2)},{(3.4)})
在写这篇文章的时候,我想到了使用一个单独的JOIN:
dailyminima = FOREACH g GENERATE group as day, MIN(samples.samp) as minsamp;
dailyminima = JOIN samples BY (day, samp), dailyminima BY (day, minsamp);
这项工作,但结果(在实际情况下)在两个大型数据集的连接中,而不是搜索一天的值,这看起来并不健康。
在实际情况中,我实际上想要找到最大值和最小值以及相关时间。我希望嵌套表达式方法可以让我同时做到这两点。
对此方法的建议将不胜感激。
答案 0 :(得分:3)
感谢alexeipab提供another SO question的链接。
一个有效的解决方案(找到最小值和最大值以及相关时间)是:
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);
};
答案 1 :(得分:0)
另一种方法,它的优点是它不会对整个关系进行排序,只保留(潜在)min在内存中,就是使用PiggyBank ExtremalTupleByNthField.这个UDF实现了累加器和代数并且非常有效。
您的代码看起来像这样:
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 作为第一个参数来定义的。