[英]How to dynamically get Top N percent records within group in Pig
我有一個問題,我不確定如何用Pig解決。 我在Hadoop上有一個數據集(約400萬條記錄),其中包含按產品類別列出的產品標題。 每個標題都有編號。 它出現在網頁上的次數,沒有。 單擊它的次數可以轉到產品詳細信息頁面。 沒有 產品類別中的標題可能有所不同。
樣本數據 -
電子游戲|光環4 | 5400 | 25
電子游戲| Forza Motorsport 4限量珍藏版| 6000 | 10
電子游戲|漫威極限聯盟| 2000 | 55
相機和照片|適用於GoPro HD的Pro Steadicam | 12000 | 250
相機和照片|英雄GoPro Motorsports 1080P寬屏高清5MP頭盔攝像機| 10000 | 125
我想根據第三列(網頁上的外觀)獲取每個產品類別中前N%個記錄。 但是,N%必須根據類別的重量/重要性而變化。 例如。 對於電子游戲,我想獲得前15%的記錄; 對於Camera&Photo,我想獲得前5%的值,等等。有沒有辦法在Pig中嵌套的FOREACH代碼塊內的LIMIT子句中動態設置%或Integer值?
PRODUCT_DATA = LOAD '<PRODUCT FILE PATH>' USING PigStorage('|') AS (categ_name:chararray, product_titl:chararray, impression_cnt:long, click_through_cnt:long);
GRP_PROD_DATA = GROUP PRODUCT_DATA BY categ_name;
TOP_PROD_LIST = FOREACH GRP_PROD_DATA {
SORTED_TOP_PROD = ORDER PRODUCT_DATA BY impression_cnt DESC;
SAMPLED_DATA = LIMIT SORTED_TOP_PROD <CATEGORY % OR INTEGER VALUE>;
GENERATE flatten(SAMPLED_DATA);
}
STORE TOP_PROD_TITLE_LIST INTO '<SOME PATH>' USING PigStorage('|');
如何動態(按類別)設置給定組的%或整數值? 我想到要使用MACRO,但無法從NESTED FOREACH塊中調用MACROS。 是否可以編寫將類別名稱作為參數並輸出%OR INTEGER值的UDF,並從LIMIT操作中調用此UDF?
SAMPLED_DATA = LIMIT SORTED_TOP_PROD categLimitVal(categ_name);
有什么建議么? 我正在使用Pig的0.10版本。
這樣的事情可能會起作用。 但是,我從未需要在Pig映射中查找變量鍵,而另一個SO問題沒有答案,因此您需要進行一些嘗試和錯誤才能使其起作用:
--Load your dynamic percentages as a map
A = LOAD 'percentages' AS (categ_name:chararray, perc:float);
PERCENTAGES = FOREACH A GENERATE TOMAP(categ_name, perc);
PRODUCT_DATA = LOAD ...;
GRP_PROD_DATA = GROUP PRODUCT_DATA BY categ_name;
--Count the elements per group; needed to calculate pecentages
C = FOREACH GRP_PROD_DATA generate FLATTEN(group) AS categ_name, COUNT(*) as count;
c_MAP = FOREACH C GENERATE TOMAP(categ_name, count);
TOP_PROD_LIST = FOREACH GRP_PROD_DATA {
SORTED_TOP_PROD = ORDER PRODUCT_DATA BY impression_cnt DESC;
SAMPLED_DATA = LIMIT SORTED_TOP_PROD (C_MAP#group * PERCENTAGES#group);
GENERATE flatten(SAMPLED_DATA);
}
您也可以嘗試使用Pig的TOP
函數代替ORDER
+ LIMIT
。
我想我使用稍微不同的方法解決了它。 我不確定它的優化程度如何,也許有更好的方法來組織/優化腳本。 基本上,如果我按印象計數的ASC
順序對每個類別中的產品標題進行排名,並且在類別的RANK
<= SAMPLE LIMIT
時進行過濾,那么我可以模擬動態采樣。 該SAMPLE LIMIT
不過是COUNT
每個類別*職稱的PERCENT WEIGHT
每個類別定義。 為了RANK
元組,我利用LinkedIn的DataFu開放源代碼的jar,提供了一個ENUMERATE
UDF。
再說一次,如果有人對改進/更好地組織代碼提出建議,我非常高興:)感謝您輸入Cabad,它真的很有幫助!
腳本:
REGISTER '/tmp/udf/datafu-1.0.0.jar';
define Enumerate datafu.pig.bags.Enumerate('1');
set default_parallel 10;
LKP_DATA = LOAD '/tmp/lkp.dat' USING PigStorage('|') AS (categ_name:chararray, perc:float);
PRODUCT_DATA = LOAD '/tmp/meta.dat' USING PigStorage('|') AS (categ_name:chararray, product_titl:chararray, impression_cnt:long, click_through_cnt:long);
GRP_PROD_DATA = GROUP PRODUCT_DATA BY categ_name;
CATEG_COUNT = FOREACH GRP_PROD_DATA generate FLATTEN(group) AS categ_name, COUNT(PRODUCT_DATA) as cnt;
CATEG_JOINED = JOIN CATEG_COUNT BY categ_name, LKP_DATA BY categ_name USING 'replicated';
CATEG_PERCENT = FOREACH CATEG_JOINED GENERATE CATEG_COUNT::categ_name AS categ_name, CATEG_COUNT::cnt AS record_cnt, LKP_DATA::perc AS percentage;
PRCNT_PROD_DATA = JOIN PRODUCT_DATA BY categ_name, CATEG_PERCENT BY categ_name;
PRCNT_PROD_DATA = FOREACH PRCNT_PROD_DATA GENERATE PRODUCT_DATA::categ_name AS categ_name, PRODUCT_DATA::product_titl AS product_titl, PRODUCT_DATA::impression_cnt AS impression_cnt, PRODUCT_DATA::click_through_cnt AS click_through_cnt, CATEG_PERCENT::record_cnt*CATEG_PERCENT::percentage AS sample_size;
GRP_PRCNT_PROD_DATA = GROUP PRCNT_PROD_DATA BY categ_name;
ORDRD_PROD_LIST = FOREACH GRP_PRCNT_PROD_DATA {
SORTED_TOP_PROD = ORDER PRCNT_PROD_DATA BY impression_cnt DESC;
GENERATE flatten(SORTED_TOP_PROD);
}
GRP_PROD_LIST = GROUP ORDRD_PROD_LIST BY categ_name;
GRP_PRCNT_PROD_DATA = FOREACH GRP_PROD_LIST GENERATE flatten(Enumerate(ORDRD_PROD_LIST)) AS (categ_name, product_titl, impression_cnt, click_through_cnt, sample_size, rnk);
SAMPLED_DATA = FILTER GRP_PRCNT_PROD_DATA BY rnk <= sample_size;
SAMPLED_DATA = FOREACH SAMPLED_DATA GENERATE categ_name, product_titl, impression_cnt, click_through_cnt, rnk;
DUMP SAMPLED_DATA;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.