Pyspark Join操作

Spark Join 操作

[TOC]

官方文檔:https://spark.apache.org/docs/2.4.7/api/python/pyspark.sql.html?highlight=join#pyspark.sql.DataFrame.join

從文檔中可以看到關(guān)于join的介紹:join(other, on=None, how=None)

從函數(shù)中可以看到有三個參數(shù):

  • other:需要合并的DataFrame格式的數(shù)據(jù)涕癣。官方寫的是Right side of the join只泼,翻譯過來就是放在右側(cè)的DataFrame數(shù)據(jù)莲祸。
  • on:用來執(zhí)行對等連接的列名,可以是字符串沛硅、字符串列表或者表達(dá)式。如果是字符串或者字符串列表养匈,那么兩邊的數(shù)據(jù)都得存在該列秋度。spark的橫向合并不向pandas那么簡單芍秆,直接橫向拼接。spark合并必須有對應(yīng)的列作為參照翠勉,列值形同的就合并妖啥,不存在的就填充空值。
  • how:合并方式对碌。默認(rèn)的是inner荆虱,其他的還有cross,outer朽们,full怀读,full_outer,left骑脱,left_outer菜枷,right,right_outer叁丧,left_semi啤誊,left_anti。

一.創(chuàng)建數(shù)據(jù)

首先創(chuàng)建如下兩組數(shù)據(jù):

score.png

我將在這兩組數(shù)據(jù)基礎(chǔ)上做些測試拥娄。

創(chuàng)建代碼:

# -*- coding: utf-8 -*-
from pyspark.sql import SparkSession

spark = SparkSession \
    .builder \
    .master("local") \
    .appName("create df") \
    .getOrCreate()

# 第一組數(shù)據(jù)蚊锹,包含年齡、體重条舔、身高信息
body_info = [["Bom", 20, 97.6, 165],
             ["Alice", 23, 90.0, 160],
             ["kuke", 33, 190.0, 170],
             ["jike", 19, 120.0, 170],
             ["Joe", 24, 89.0, 162]]

body_df = spark.createDataFrame(body_info, ["name", "age", "weight", "height"])
body_df.show()

# 第二組數(shù)據(jù)枫耳,包含一些成績信息,語數(shù)外
score_info = [["Bom", 88, 97, 90],
             ["Alice", 85, 99, 92],
             ["kuke", 77, 82, 80],
             ["jike", 65, 58, 30],
             ["Joe", 90, 100, 92]]
score_df = spark.createDataFrame(score_info, ["name", "Chinese", "Math", "English"])
score_df.show()


# 輸出
+-----+---+------+------+
| name|age|weight|height|
+-----+---+------+------+
|  Bom| 20|  97.6|   165|
|Alice| 23|  90.0|   160|
| kuke| 33| 190.0|   170|
| jike| 19| 120.0|   170|
|  Joe| 24|  89.0|   162|
+-----+---+------+------+

+-----+-------+----+-------+
| name|Chinese|Math|English|
+-----+-------+----+-------+
|  Bom|     88|  97|     90|
|Alice|     85|  99|     92|
| kuke|     77|  82|     80|
| jike|     65|  58|     30|
|  Joe|     90| 100|     92|
+-----+-------+----+-------+

二.合并操作

這節(jié)的操作只針對第三個參數(shù)how做實驗孟抗,第二個參數(shù)on都設(shè)為name迁杨。

1.inner

情況一:第一組數(shù)據(jù)行數(shù) = 第二組數(shù)據(jù)行數(shù)

合并代碼:

merge_df = body_df.join(score_df, on="name", how="inner")
merge_df.show()

輸出

+-----+---+------+------+-------+----+-------+
| name|age|weight|height|Chinese|Math|English|
+-----+---+------+------+-------+----+-------+
| jike| 19| 120.0|   170|     65|  58|     30|
|  Bom| 20|  97.6|   165|     88|  97|     90|
|  Joe| 24|  89.0|   162|     90| 100|     92|
|Alice| 23|  90.0|   160|     85|  99|     92|
| kuke| 33| 190.0|   170|     77|  82|     80|
+-----+---+------+------+-------+----+-------+

結(jié)果顯而易見,是把第二組數(shù)據(jù)除name列拼到了第一組的右邊凄硼。

情況二:第一組數(shù)據(jù)行數(shù) > 第二組數(shù)據(jù)行數(shù)

刪掉第二組數(shù)據(jù)的2和4行铅协,變?yōu)椋?/p>

+-----+-------+----+-------+
| name|Chinese|Math|English|
+-----+-------+----+-------+
|  Bom|     88|  97|     90|
| kuke|     77|  82|     80|
|  Joe|     90| 100|     92|
+-----+-------+----+-------+

合并代碼:

merge_df = body_df.join(score_df, on="name", how="inner")
merge_df.show()

輸出:

+----+---+------+------+-------+----+-------+
|name|age|weight|height|Chinese|Math|English|
+----+---+------+------+-------+----+-------+
| Bom| 20|  97.6|   165|     88|  97|     90|
| Joe| 24|  89.0|   162|     90| 100|     92|
|kuke| 33| 190.0|   170|     77|  82|     80|
+----+---+------+------+-------+----+-------+

從輸出結(jié)果可以看到,inner操作先根據(jù)兩組的name列求交集摊沉,再合并數(shù)據(jù)狐史。

情況三:第一組數(shù)據(jù)行數(shù) < 第二組數(shù)據(jù)行數(shù)

刪掉第一組數(shù)據(jù)的2和4行,變?yōu)椋?/p>

+-----+---+------+------+
| name|age|weight|height|
+-----+---+------+------+
|  Bom| 20|  97.6|   165|
| kuke| 33| 190.0|   170|
|  Joe| 24|  89.0|   162|
+-----+---+------+------+

合并代碼:

merge_df = body_df.join(score_df, on="name", how="inner")
merge_df.show()

輸出:

+----+---+------+------+-------+----+-------+
|name|age|weight|height|Chinese|Math|English|
+----+---+------+------+-------+----+-------+
| Bom| 20|  97.6|   165|     88|  97|     90|
| Joe| 24|  89.0|   162|     90| 100|     92|
|kuke| 33| 190.0|   170|     77|  82|     80|
+----+---+------+------+-------+----+-------+

結(jié)果和情況二一樣说墨,先求交集骏全,在合并。

2.cross

情況一:第一組數(shù)據(jù)行數(shù) = 第二組數(shù)據(jù)行數(shù)

合并代碼:

merge_df = body_df.join(score_df, on="name", how="cross")
merge_df.show()

在spark2.4.7中用上邊的代碼運行會毫不客氣的報錯:

pyspark.sql.utils.IllegalArgumentException: 'requirement failed: Unsupported using join type Cross'

之后通過Google尼斧,搜索到不是這么用:

改成如下:

merge_df = body_df.crossJoin(score_df)
merge_df.show()

輸出:

+-----+---+------+------+-----+-------+----+-------+
| name|age|weight|height| name|Chinese|Math|English|
+-----+---+------+------+-----+-------+----+-------+
|  Bom| 20|  97.6|   165|  Bom|     88|  97|     90|
|  Bom| 20|  97.6|   165|Alice|     85|  99|     92|
|  Bom| 20|  97.6|   165| kuke|     77|  82|     80|
|  Bom| 20|  97.6|   165| jike|     65|  58|     30|
|  Bom| 20|  97.6|   165|  Joe|     90| 100|     92|
|Alice| 23|  90.0|   160|  Bom|     88|  97|     90|
|Alice| 23|  90.0|   160|Alice|     85|  99|     92|
|Alice| 23|  90.0|   160| kuke|     77|  82|     80|
|Alice| 23|  90.0|   160| jike|     65|  58|     30|
|Alice| 23|  90.0|   160|  Joe|     90| 100|     92|
| kuke| 33| 190.0|   170|  Bom|     88|  97|     90|
| kuke| 33| 190.0|   170|Alice|     85|  99|     92|
| kuke| 33| 190.0|   170| kuke|     77|  82|     80|
| kuke| 33| 190.0|   170| jike|     65|  58|     30|
| kuke| 33| 190.0|   170|  Joe|     90| 100|     92|
| jike| 19| 120.0|   170|  Bom|     88|  97|     90|
| jike| 19| 120.0|   170|Alice|     85|  99|     92|
| jike| 19| 120.0|   170| kuke|     77|  82|     80|
| jike| 19| 120.0|   170| jike|     65|  58|     30|
| jike| 19| 120.0|   170|  Joe|     90| 100|     92|
+-----+---+------+------+-----+-------+----+-------+

看到這結(jié)果開始有點摸不著頭腦姜贡,后來看懂了是第一組數(shù)據(jù)的每一行都會和第二組的每一行生成新的一行。

情況二:第一組數(shù)據(jù)行數(shù) > 第二組數(shù)據(jù)行數(shù)

刪掉第二組數(shù)據(jù)的2和4行棺棵,變?yōu)椋?/p>

+-----+-------+----+-------+
| name|Chinese|Math|English|
+-----+-------+----+-------+
|  Bom|     88|  97|     90|
| kuke|     77|  82|     80|
|  Joe|     90| 100|     92|
+-----+-------+----+-------+

合并代碼:

merge_df = body_df.crossJoin(score_df)
merge_df.show()

輸出:

+-----+---+------+------+----+-------+----+-------+
| name|age|weight|height|name|Chinese|Math|English|
+-----+---+------+------+----+-------+----+-------+
|  Bom| 20|  97.6|   165| Bom|     88|  97|     90|
|  Bom| 20|  97.6|   165|kuke|     77|  82|     80|
|  Bom| 20|  97.6|   165| Joe|     90| 100|     92|
|Alice| 23|  90.0|   160| Bom|     88|  97|     90|
|Alice| 23|  90.0|   160|kuke|     77|  82|     80|
|Alice| 23|  90.0|   160| Joe|     90| 100|     92|
| kuke| 33| 190.0|   170| Bom|     88|  97|     90|
| kuke| 33| 190.0|   170|kuke|     77|  82|     80|
| kuke| 33| 190.0|   170| Joe|     90| 100|     92|
| jike| 19| 120.0|   170| Bom|     88|  97|     90|
| jike| 19| 120.0|   170|kuke|     77|  82|     80|
| jike| 19| 120.0|   170| Joe|     90| 100|     92|
|  Joe| 24|  89.0|   162| Bom|     88|  97|     90|
|  Joe| 24|  89.0|   162|kuke|     77|  82|     80|
|  Joe| 24|  89.0|   162| Joe|     90| 100|     92|
+-----+---+------+------+----+-------+----+-------+

雖然少了兩行楼咳,但不影響情況一對結(jié)論熄捍。

情況三:第一組數(shù)據(jù)行數(shù) < 第二組數(shù)據(jù)行數(shù)

刪掉第一組數(shù)據(jù)的2和4行,變?yōu)椋?/p>

+-----+---+------+------+
| name|age|weight|height|
+-----+---+------+------+
|  Bom| 20|  97.6|   165|
| kuke| 33| 190.0|   170|
|  Joe| 24|  89.0|   162|
+-----+---+------+------+

合并代碼:

merge_df = body_df.crossJoin(score_df)
merge_df.show()

輸出:

+----+---+------+------+-----+-------+----+-------+
|name|age|weight|height| name|Chinese|Math|English|
+----+---+------+------+-----+-------+----+-------+
| Bom| 20|  97.6|   165|  Bom|     88|  97|     90|
| Bom| 20|  97.6|   165|Alice|     85|  99|     92|
| Bom| 20|  97.6|   165| kuke|     77|  82|     80|
| Bom| 20|  97.6|   165| jike|     65|  58|     30|
| Bom| 20|  97.6|   165|  Joe|     90| 100|     92|
|kuke| 33| 190.0|   170|  Bom|     88|  97|     90|
|kuke| 33| 190.0|   170|Alice|     85|  99|     92|
|kuke| 33| 190.0|   170| kuke|     77|  82|     80|
|kuke| 33| 190.0|   170| jike|     65|  58|     30|
|kuke| 33| 190.0|   170|  Joe|     90| 100|     92|
| Joe| 24|  89.0|   162|  Bom|     88|  97|     90|
| Joe| 24|  89.0|   162|Alice|     85|  99|     92|
| Joe| 24|  89.0|   162| kuke|     77|  82|     80|
| Joe| 24|  89.0|   162| jike|     65|  58|     30|
| Joe| 24|  89.0|   162|  Joe|     90| 100|     92|
+----+---+------+------+-----+-------+----+-------+

結(jié)論和情況一一樣母怜。

3.outer

情況一:第一組數(shù)據(jù)行數(shù) = 第二組數(shù)據(jù)行數(shù)

合并代碼:

merge_df = body_df.join(score_df, on="name", how="outer")
merge_df.show()

輸出:

+-----+---+------+------+-------+----+-------+
| name|age|weight|height|Chinese|Math|English|
+-----+---+------+------+-------+----+-------+
| jike| 19| 120.0|   170|     65|  58|     30|
|  Bom| 20|  97.6|   165|     88|  97|     90|
|  Joe| 24|  89.0|   162|     90| 100|     92|
|Alice| 23|  90.0|   160|     85|  99|     92|
| kuke| 33| 190.0|   170|     77|  82|     80|
+-----+---+------+------+-------+----+-------+

結(jié)果和inner合并的情況一一樣余耽,結(jié)論暫時未知。

情況二:第一組數(shù)據(jù)行數(shù) > 第二組數(shù)據(jù)行數(shù)

刪掉第二組數(shù)據(jù)的2和4行苹熏,變?yōu)椋?/p>

+-----+-------+----+-------+
| name|Chinese|Math|English|
+-----+-------+----+-------+
|  Bom|     88|  97|     90|
| kuke|     77|  82|     80|
|  Joe|     90| 100|     92|
+-----+-------+----+-------+

合并代碼:

merge_df = body_df.join(score_df, on="name", how="outer")
merge_df.show()

輸出:

+-----+---+------+------+-------+----+-------+
| name|age|weight|height|Chinese|Math|English|
+-----+---+------+------+-------+----+-------+
| jike| 19| 120.0|   170|   null|null|   null|
|  Bom| 20|  97.6|   165|     88|  97|     90|
|  Joe| 24|  89.0|   162|     90| 100|     92|
|Alice| 23|  90.0|   160|   null|null|   null|
| kuke| 33| 190.0|   170|     77|  82|     80|
+-----+---+------+------+-------+----+-------+

從輸出結(jié)果可以看到碟贾,沒有的數(shù)據(jù)用null填充。

情況三:第一組數(shù)據(jù)行數(shù) < 第二組數(shù)據(jù)行數(shù)

刪掉第一組數(shù)據(jù)2和4行轨域,變?yōu)椋?/p>

+-----+---+------+------+
| name|age|weight|height|
+-----+---+------+------+
|  Bom| 20|  97.6|   165|
| kuke| 33| 190.0|   170|
|  Joe| 24|  89.0|   162|
+-----+---+------+------+

合并代碼:

merge_df = body_df.join(score_df, on="name", how="outer")
merge_df.show()

輸出:

+-----+----+------+------+-------+----+-------+
| name| age|weight|height|Chinese|Math|English|
+-----+----+------+------+-------+----+-------+
| jike|null|  null|  null|     65|  58|     30|
|  Bom|  20|  97.6|   165|     88|  97|     90|
|  Joe|  24|  89.0|   162|     90| 100|     92|
|Alice|null|  null|  null|     85|  99|     92|
| kuke|  33| 190.0|   170|     77|  82|     80|
+-----+----+------+------+-------+----+-------+

結(jié)合前面兩種情況缕陕,先根據(jù)name列的值求并集,有數(shù)據(jù)的直接合并疙挺,沒有的填充null。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怜浅,一起剝皮案震驚了整個濱河市铐然,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恶座,老刑警劉巖搀暑,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異跨琳,居然都是意外死亡自点,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門脉让,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桂敛,“玉大人,你說我怎么就攤上這事溅潜∈趸#” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵滚澜,是天一觀的道長粗仓。 經(jīng)常有香客問我,道長设捐,這世上最難降的妖魔是什么借浊? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮萝招,結(jié)果婚禮上蚂斤,老公的妹妹穿的比我還像新娘。我一直安慰自己即寒,他們只是感情好橡淆,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布召噩。 她就那樣靜靜地躺著,像睡著了一般逸爵。 火紅的嫁衣襯著肌膚如雪具滴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天师倔,我揣著相機與錄音构韵,去河邊找鬼。 笑死趋艘,一個胖子當(dāng)著我的面吹牛疲恢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瓷胧,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼显拳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搓萧?” 一聲冷哼從身側(cè)響起杂数,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘸洛,沒想到半個月后揍移,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡反肋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年那伐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片石蔗。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡罕邀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出养距,到底是詐尸還是另有隱情燃少,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布铃在,位于F島的核電站阵具,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏定铜。R本人自食惡果不足惜阳液,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望揣炕。 院中可真熱鬧帘皿,春花似錦、人聲如沸畸陡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至曹动,卻和暖如春斋日,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背墓陈。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工恶守, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贡必。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓兔港,卻偏偏與公主長得像,于是被迫代替她去往敵國和親仔拟。 傳聞我的和親對象是個殘疾皇子衫樊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

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