2012-11-12 34 views
3

我有時間戳樣本,我正在使用豬處理它們。我想每天查找樣本的最小值以及最小值的時間。所以我需要選擇包含最小值的樣本的記錄。我怎樣才能選擇最小值拉丁豬記錄

爲簡單起見,我將在兩個字段中表示時間,第一個是一天,第二個是一天中的「時間」。

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)}) 

在寫這個我想用一個單獨的連接:

dailyminima = FOREACH g GENERATE group as day, MIN(samples.samp) as minsamp; 
dailyminima = JOIN samples BY (day, samp), dailyminima BY (day, minsamp); 

這項工作,但結果(實際情況)中加入了兩個大型數據集,而不是通過一個單一的一天的值的搜索,這沒有按看起來不健康。

在真實情況下,我確實想要查找最大和最小以及相關時間。我希望嵌套的表達方法能讓我一次完成這兩個操作。

建議如何解決這個問題將不勝感激。

+0

您可以使用嵌套在FOREACH中的ORDER和LIMIT。看到類似的問題http:// stackoverflow。com/questions/13253863/access-an-element-like-array-in-pig – alexeipab

+0

謝謝alexeipab - 這引導我找到了一個可行的解決方案,並且在這種情況下是一個很好的解決方案。我會盡快添加答案。我仍然想明白爲什麼MIN和FILTER的組合不起作用,以及爲什麼FILTER在沒有MIN的情況下工作,但是當首先應用MIN時失敗。 – hamish

回答

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); 
}; 
0

另一種方式來做到這一點,它有它不整個關係進行排序的優勢,並且只保留內存中的(潛在)最小值是使用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語句定義排序的事實。