簡體   English   中英

如何動態獲取Pig組中的前N個百分比記錄

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM