reduceByKey應(yīng)用舉例

Photo by Stefan Stefancik from Pexels

在進行Spark開發(fā)算法時,最有用的一個函數(shù)就是reduceByKey临扮。

reduceByKey的作用對像是(key, value)形式的rdd者蠕,而reduce有減少、壓縮之意桩了,reduceByKey的作用就是對相同key的數(shù)據(jù)進行處理,最終每個key只保留一條記錄埠戳。

保留一條記錄通常有兩種結(jié)果井誉。一種是只保留我們希望的信息,比如每個key出現(xiàn)的次數(shù)整胃。第二種是把value聚合在一起形成列表颗圣,這樣后續(xù)可以對value做進一步的操作,比如排序屁使。

常用方式舉例

比如現(xiàn)在我們有數(shù)據(jù)goodsSale:RDD[(String, String)]在岂,兩個字段分別是goodsid、單個訂單中的銷售額蛮寂,現(xiàn)在我們需要統(tǒng)計每個goodsid的銷售額蔽午。

我們只需要保留每個goodsid的累記銷售額,可以使用如下語句來實現(xiàn):


val goodsSaleSum = goodsSale.reduceByKey((x,y) => x+y)

熟悉之后你可以使用更簡潔的方式:


val goodsSaleSum = goodsSale.reduceByKey(_+_)

reduceByKey會尋找相同key的數(shù)據(jù)酬蹋,當(dāng)找到這樣的兩條記錄時會對其value(分別記為x,y)做(x,y) => x+y的處理及老,即只保留求和之后的數(shù)據(jù)作為value。反復(fù)執(zhí)行這個操作直至每個key只留下一條記錄范抓。

現(xiàn)在假設(shè)goodsSaleSum還有一個字段類目id骄恶,即 RDD[(String, String, String)] 形式,三個字段分別是類目id匕垫、goodsid叠蝇、總銷量,現(xiàn)在我們要獲得第個類目id下銷量最高的一個商品年缎。

上一步聚是保留value求和之后的數(shù)據(jù)悔捶,而這里其實我們只需要保留銷量更高的那條記錄。不過我們不能直接對RDD[(String, String, String)]類型的數(shù)據(jù)使用reduceByKey方法单芜,因為這并不是一個(key, value)形式的數(shù)據(jù)蜕该,所以需要使用map方法轉(zhuǎn)化一下類型。


val catGmvTopGoods = goodsSaleSum.map(x => (x._1, (x._2, x._3)))

    .reduceByKey((x, y) => if (x._2.toDouble > y._2.toDouble) x else y)

    .map(x => (x._1, x._2._1, x._2._2)

再進一步洲鸠,假設(shè)現(xiàn)在我們有一個任務(wù):推薦5個銷售額最高的類目堂淡,并為每個類目推薦一個銷售額最高的商品,而我們的數(shù)據(jù)就是上述RDD[(String, String, String)類型的goodsSaleSum扒腕。

這需要兩步绢淀,一是計算每個類目的銷售額,這和舉的第一個例子一樣瘾腰。二是找出每個類目下銷量最高的商品皆的,這和第二個例子一樣。實際上蹋盆,我們可以只實用一個reduceByKey就達到上面的目的费薄。


val catIdGmvTopGoods = goodsSaleSum.map(x => (x._1, (x._2, x._3, x._3)))

    .reduceByKey((x, y) => if (x._2 > y._2) (x._1, x._2, x._3+y._3) else (y._1, y._2, x._3+y._3))

    .map( x => (x._1, x._2._1, x._2._2, x._2._3)

    .sortBy(_._3, false)

    .take(5)

由于我們需要計算每個類目的總銷售額硝全,同時需要保留商品的銷售額,所以先使用map增加一個字段用來記錄類目的總銷售額楞抡。這樣一來伟众,我們就可以使用reduceByKey同時完成前兩個例子的操作。

剩下的就是進行排序并獲取前5條記錄召廷。

聚合方式舉例

上述的三個例子都是只保留需要的信息凳厢,但有時我們需要將value聚合在一起進行排序操作,比如對每個類目下的商品按銷售額進行排序竞慢。

假設(shè)我們的數(shù)據(jù)是 RDD[(String, String, String)]数初,三個字段分別是類目id、goodsid梗顺、銷售額泡孩。

若是使用sql,那我們直接用row_number函數(shù)就可以很簡單的使用分類目排序這個任務(wù)寺谤。

但由于spark-sql占用的資源會比RDD多不少仑鸥,在開發(fā)任務(wù)時并不建議使用spark-sql。

我們的方法是通過reduceByKey把商品聚合成一個List变屁,然后對這個List進行排序眼俊,再使用flatMapValues攤平數(shù)據(jù)。

我們在使用reduceyByKey時會注意到粟关,兩個value聚合后的數(shù)據(jù)類型必須和之前一致疮胖。

所以在聚合商品時我們也需要保證這點,通常有兩種方法闷板,一是使用ListBuffer澎灸,即可變長度的List。二是使用String遮晚,以分隔符來區(qū)分商品和銷售額性昭。下面我們使用第一種方式完成這個任務(wù)。


val catIdGoodsIdSorted = goodsGmvSum.map(x => (x._1, ListBuffer(x._2, x._3.toDouble)))

    .reduceByKey((x, y) => x++y)

    .flatMapValues( x => x.toList.sortBy(_._2).reverse.zipWithIndex)

上述zipWithIndex給列表增加一個字段县遣,用來記錄元素的位置信息糜颠。而flatMapValues可以把List的每個元素單獨拆成一條記錄,詳細的說明可以參考我寫的另一篇文章Spark入門-常用函數(shù)匯總

小結(jié)

我在本文中介紹了reduceByKey的三種作用:

  1. 求和匯總

  2. 獲得每個key下value最大的記錄

  3. 聚合value形成一個List之后進行排序

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末萧求,一起剝皮案震驚了整個濱河市其兴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌夸政,老刑警劉巖元旬,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡法绵,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門酪碘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朋譬,“玉大人,你說我怎么就攤上這事兴垦♂阌” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵探越,是天一觀的道長狡赐。 經(jīng)常有香客問我,道長钦幔,這世上最難降的妖魔是什么枕屉? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮鲤氢,結(jié)果婚禮上搀擂,老公的妹妹穿的比我還像新娘。我一直安慰自己卷玉,他們只是感情好哨颂,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著相种,像睡著了一般威恼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寝并,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天箫措,我揣著相機與錄音,去河邊找鬼衬潦。 笑死蒂破,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的别渔。 我是一名探鬼主播附迷,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哎媚!你這毒婦竟也來了喇伯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤拨与,失蹤者是張志新(化名)和其女友劉穎稻据,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡捻悯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年匆赃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片今缚。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡算柳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出姓言,到底是詐尸還是另有隱情瞬项,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布何荚,位于F島的核電站囱淋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏餐塘。R本人自食惡果不足惜妥衣,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望戒傻。 院中可真熱鬧称鳞,春花似錦、人聲如沸稠鼻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽候齿。三九已至熙暴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慌盯,已是汗流浹背周霉。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亚皂,地道東北人俱箱。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像灭必,于是被迫代替她去往敵國和親狞谱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1.1禁漓、 分配更多資源 1.1.1跟衅、分配哪些資源? Executor的數(shù)量 每個Executor所能分配的CPU數(shù)...
    miss幸運閱讀 3,176評論 3 15
  • 1播歼、 性能調(diào)優(yōu) 1.1伶跷、 分配更多資源 1.1.1、分配哪些資源? Executor的數(shù)量 每個Executor所...
    Frank_8942閱讀 4,529評論 2 36
  • Spark 編程指南 概述 Spark 依賴 初始化 Spark 使用 Shell 彈性分布式數(shù)據(jù)集 (RDDs)...
    Joyyx閱讀 1,850評論 0 4
  • 轉(zhuǎn)眼2017年已經(jīng)過了一半多了叭莫,回顧這半年感覺就像一場夢蹈集。或悲或喜雇初,或迷寐K粒或堅持,或勇往直前或畏首畏...
    尋找前行的路閱讀 185評論 0 1
  • 今天語文老師給我們上了一節(jié)自學(xué)課辩蛋,這節(jié)語文課 老師讓我們自學(xué)生字呻畸,老師讓我們自學(xué)的生字是這些,問半你有從悼院,是這些生...
    子細閱讀 143評論 0 0