ใน
บทที่แล้วได้เขียนถึงวิธีการเอาข้อมูลจากตารางสองอันขึ้นไปมารวมเข้าด้วยกันแล้ว สำหรับในบทนี้จะเป็นเรื่องของการรวมสองตารางเข้าด้วยกันเช่นกันเพียงแต่ว่าเป็นการรวมในอีกลักษณะหนึ่ง นั่นคือการเชื่อมโดยผ่านความสัมพันธ์ของค่าภายในตาราง    
การเชื่อมข้อมูลโดยผ่านคอลัมน์ที่ชื่อเหมือนกัน หากมีตารางเดตาเฟรมสองอันแล้วต้องการนำข้อมูลมาเชื่อมต่อรวมกันโดยอาศัยคอลัมน์หนึ่งเป็นตัวเชื่อมสามารถใช้ฟังก์ชัน pd.merge 
 ตัวอย่าง มีข้อมูลของโปเกมอนอยู่สองตาราง ตารางแรกบอกชนิดของโปเกมอน ส่วนอีกตารางบอกส่วนสูงและน้ำหนัก ทั้งสองตารางมีสองแถวแรกเป็นหมายเลขและสายพันธุ์ของโปเกมอนเหมือนกัน
import pandas as pd
 pokemon_chanit = pd.DataFrame([
         [69,'มาดัตสึโบมิ','พืช/พิษ'],
         [72,'เมโนคุราเงะ','น้ำ/พิษ'],
         [74,'อิชิตสึบุเตะ','หิน/ดิน']],
     columns=['หมายเลข','สายพันธุ์','ชนิด'])
 pokemon_sungnak = pd.DataFrame([
         [69,'มาดัตสึโบมิ',0.7,4.0],
         [72,'เมโนคุราเงะ',0.9,45.5],
         [74,'อิชิตสึบุเตะ',0.4,20.0]],
     columns=['หมายเลข','สายพันธุ์','ส่วนสูง','น้ำหนัก'])
 print(pokemon_chanit)
 print(pokemon_sungnak)
 print(pd.merge(pokemon_chanit,pokemon_sungnak))
 
 
 
   ได้
|   | 
หมายเลข | 
สายพันธุ์ | 
ชนิด | 
| 0 | 
69 | 
มาดัตสึโบมิ | 
พืช/พิษ | 
| 1 | 
72 | 
เมโนคุราเงะ | 
น้ำ/พิษ | 
| 2 | 
74 | 
อิชิตสึบุเตะ | 
หิน/ดิน | 
|   | 
หมายเลข | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
| 0 | 
69 | 
มาดัตสึโบมิ | 
0.7 | 
4.0 | 
| 1 | 
72 | 
เมโนคุราเงะ | 
0.9 | 
45.5 | 
| 2 | 
74 | 
อิชิตสึบุเตะ | 
0.4 | 
20.0 | 
|   | 
หมายเลข | 
สายพันธุ์ | 
ชนิด | 
ส่วนสูง | 
น้ำหนัก | 
| 0 | 
69 | 
มาดัตสึโบมิ | 
พืช/พิษ | 
0.7 | 
4.0 | 
| 1 | 
72 | 
เมโนคุราเงะ | 
น้ำ/พิษ | 
0.9 | 
45.5 | 
| 2 | 
74 | 
อิชิตสึบุเตะ | 
หิน/ดิน | 
0.4 | 
20.0 | 
 
 จะเห็นว่าพอรวมกันแล้วได้ตารางที่มีชนิด, ส่วนสูง และน้ำหนัก โดยที่หมายเลขและสายพันธุ์ก็ยังอยู่และเหมือนเดิม ในที่นี้หมายเลขและสายพันธุ์ถูกใช้เป็นตัวเชื่อม 
 ปกติถ้าไม่ได้ระบุอะไรละก็คอลัมน์ที่ซ้ำกันในทั้งสองตารางจะถูกใช้เป็นตัวเชื่อม แต่หากระบุไว้คอลัมน์ที่ถูกใช้เชื่อมก็จะมีแค่ตัวนั้น 
 การระบุตัวเชื่อมทำได้โดยใส่คีย์เวิร์ด on เช่นลอง
print(pd.merge(pokemon_chanit,pokemon_sungnak,on='สายพันธุ์'))
 ได้
|   | 
หมายเลข_x | 
สายพันธุ์ | 
ชนิด | 
หมายเลข_y | 
ส่วนสูง | 
น้ำหนัก | 
| 0 | 
69 | 
มาดัตสึโบมิ | 
พืช/พิษ | 
69 | 
0.7 | 
4.0 | 
| 1 | 
72 | 
เมโนคุราเงะ | 
น้ำ/พิษ | 
72 | 
0.9 | 
45.5 | 
| 2 | 
74 | 
อิชิตสึบุเตะ | 
หิน/ดิน | 
74 | 
0.4 | 
20.0 | 
 
 จะเห็นว่าในที่นี้กำหนดให้ใช้แค่ "สายพันธุ์" เป็นตัวเชื่อม "หมายเลข" ไม่ได้เป็นตัวเชื่อมแล้วเลยถูกแยกออกเป็น ๒ อันแม้ว่าค่าจะเหมือนกันอยู่ก็ตาม โดยถูกเติมชื่อท้ายให้โดยอัตโนมัติ 
 ชื่อท้ายที่ถูกเติมสามารถกำหนดเองตามที่ต้องการได้โดยใส่คีย์เวิร์ด suffixes เป็นลิสต์ของสายอักขระที่ต้องการเติมต่อท้ายทั้งสองอัน เช่น
print(pd.merge(pokemon_chanit,pokemon_sungnak,on='สายพันธุ์',suffixes=[' ^_^',' +_+']))
 ได้
|   | 
หมายเลข ^_^ | 
สายพันธุ์ | 
ชนิด | 
หมายเลข +_+ | 
ส่วนสูง | 
น้ำหนัก | 
| 0 | 
69 | 
มาดัตสึโบมิ | 
พืช/พิษ | 
69 | 
0.7 | 
4.0 | 
| 1 | 
72 | 
เมโนคุราเงะ | 
น้ำ/พิษ | 
72 | 
0.9 | 
45.5 | 
| 2 | 
74 | 
อิชิตสึบุเตะ | 
หิน/ดิน | 
74 | 
0.4 | 
20.0 | 
 
   กรณีที่คอลัมน์ที่ใช้เชื่อมมีค่าซ้ำกัน ความซับซ้อนมากขึ้นในการเชื่อมโยงตารางจะเกิดขึ้นเมื่อคอลัมน์ที่ใช้เชื่อมนั้นมีที่ค่าเหมือนกันสองตัวขึ้นไป กรณีแบบนี้ข้อมูลก็จะเกิดการซ้ำตามไปด้วย 
 ลองแยกดูเป็นกรณี เริ่มจากกรณีที่มีการซ้ำแค่ในตารางใดตารางหนึ่ง 
 ตัวอย่าง สร้างตารางขึ้นมาสองอัน ตารางแรกเป็นข้อมูลโปเกมอนที่มีอยู่ อีกตารางเป็นข้อมูลของโปเกมอนแต่ละสายพันธุ์
pokemon_thimi = pd.DataFrame([
         ['พูพุริน','พูคุง',11],
         ['พิชู','พีโกะ',15],
         ['พิชู','พีสึเกะ',6],
         ['พูพุริน','พูจัง',3],
         ['โทเงปี','โทโทโระ',19],
         ['พิชู','พีนัต',7]],
     columns=['สายพันธุ์','ชื่อเล่น','เลเวล'])
 khomun_pokemon = pd.DataFrame([
         ['พิชู','ไฟฟ้า',0.3,2.0],
         ['พี','ภูต',0.3,3.0],
         ['พูพุริน','ธรรมดา/ภูต',0.3,1.0],
         ['โทเงปี','ภูต',0.3,1.5]],
     columns=['สายพันธุ์','ชนิด','ส่วนสูง','น้ำหนัก'])
 print(pokemon_thimi)
 print(khomun_pokemon)
 
 
 
 
 
 
 
 
 
 
   ได้
|   | 
สายพันธุ์ | 
ชื่อเล่น | 
เลเวล | 
| 0 | 
พูพุริน | 
พูคุง | 
11 | 
| 1 | 
พิชู | 
พีโกะ | 
15 | 
| 2 | 
พิชู | 
พีสึเกะ | 
6 | 
| 3 | 
พูพุริน | 
พูจัง | 
3 | 
| 4 | 
โทเงปี | 
โทโทโระ | 
19 | 
| 5 | 
พิชู | 
พีนัต | 
7 | 
|   | 
สายพันธุ์ | 
ชนิด | 
ส่วนสูง | 
น้ำหนัก | 
| 0 | 
พิชู | 
ไฟฟ้า | 
0.3 | 
2.0 | 
| 1 | 
พี | 
ภูต | 
0.3 | 
3.0 | 
| 2 | 
พูพุริน | 
ธรรมดา/ภูต | 
0.3 | 
1.0 | 
| 3 | 
โทเงปี | 
ภูต | 
0.3 | 
1.5 | 
 
 จากนั้นก็ลองเอามารวมกัน
print(pd.merge(pokemon_thimi,khomun_pokemon))
 ได้
|   | 
สายพันธุ์ | 
ชื่อเล่น | 
เลเวล | 
ชนิด | 
ส่วนสูง | 
น้ำหนัก | 
| 0 | 
พูพุริน | 
พูคุง | 
11 | 
ธรรมดา/ภูต | 
0.3 | 
1.0 | 
| 1 | 
พูพุริน | 
พูจัง | 
3 | 
ธรรมดา/ภูต | 
0.3 | 
1.0 | 
| 2 | 
พิชู | 
พีโกะ | 
15 | 
ไฟฟ้า | 
0.3 | 
2.0 | 
| 3 | 
พิชู | 
พีสึเกะ | 
6 | 
ไฟฟ้า | 
0.3 | 
2.0 | 
| 4 | 
พิชู | 
พีนัต | 
7 | 
ไฟฟ้า | 
0.3 | 
2.0 | 
| 5 | 
โทเงปี | 
โทโทโระ | 
19 | 
ภูต | 
0.3 | 
1.5 | 
 
 จะเห็นว่าข้อมูลจากตารางอันหลังจะปรากฏซ้ำหลายตัวในตารางที่ได้จากการรวมนี้ 
 ซึ่งความหมายในที่นี้ก็คือ สมมุติว่าตอนแรกเรารู้ว่าเรามีโปเกมอน ๖ ตัวนี้อยู่ รู้ว่ามันเป็นสายพันธุ์อะไร แต่ไม่รู้ว่ามันเป็นชนิดอะไรส่วนสูงน้ำหนักเท่าไหร่ เราก็ต้องไปเปิดดูตารางข้อมูลโปเกมอนว่าสายพันธุ์นี้มีน้ำหนักเท่าไหร่สูงเท่าไหร่เป็นชนิดไหน 
 ในที่นี้พอรู้ว่าโปเกมอนตัวนั้นเป็นพิชู ไม่ว่ามันจะชื่อเล่นว่าอะไร เลเวลเท่าไหร่ ถ้ามันเป็นพิชูมันก็จะต้องเป็นชนิดไฟฟ้า สูง 0.3 หนัก 2.0 ดังนั้นข้อมูลตรงส่วนนี้จึงออกมาซ้ำกันทั้งหมด 
 ตรงจุดนี้เราจะเห็นได้ถึงประโยชน์ของการเชื่อมข้อมูล เพราะแทนที่เราจะต้องเก็บข้อมูลของพีชูแต่ละตัวซึ่งซ้ำๆกันทั้งหมด (ชนิด, ส่วนสูง, น้ำหนัก) เราก็เก็บแค่ที่ไม่ซ้ำกันไว้ในตารางหนึ่ง (ชื่อเล่น,เลเวล) แล้วเก็บที่ซ้ำไว้ในอีกตารางโดยเก็บแค่แถวเดียว จากนั้นพอต้องการก็ค่อยเอาตารางข้อมูลมาเชื่อมกัน แบบนี้ก็จะประหยัดพื้นที่เก็บข้อมูลได้มากมาย   
 อีกกรณีหนึ่งคือถ้าหากทั้งสองตารางต่างก็มีค่าของคอลัมน์นั้นซ้ำหลายค่าเหมือนกัน
chanit = pd.DataFrame([
         ['มิโนมุจจิ','แมลง'],
         ['มิโนมาดาม','แมลง/พืช'],
         ['มิโนมาดาม','แมลง/ดิน'],
         ['มิโนมาดาม','แมลง/เหล็ก'],
         ['การ์เมล','แมลง/บิน']],
     columns=['สายพันธุ์','ชนิด'])
 phalang = pd.DataFrame([
         ['มิโนมุจจิ',29,45],
         ['มิโนมาดาม',59,85],
         ['มิโนมาดาม',79,105],
         ['มิโนมาดาม',69,95],
         ['การ์เมล',94,50]],
     columns=['สายพันธุ์','พลังโจมตี','พลังป้องกัน'])
 print(chanit)
 print(phalang)
 
 
 
 
 
   ได้
|   | 
สายพันธุ์ | 
ชนิด | 
| 0 | 
มิโนมุจจิ | 
แมลง | 
| 1 | 
มิโนมาดาม | 
แมลง/พืช | 
| 2 | 
มิโนมาดาม | 
แมลง/ดิน | 
| 3 | 
มิโนมาดาม | 
แมลง/เหล็ก | 
| 4 | 
การ์เมล | 
แมลง/บิน | 
|   | 
สายพันธุ์ | 
พลังโจมตี | 
พลังป้องกัน | 
| 0 | 
มิโนมุจจิ | 
29 | 
45 | 
| 1 | 
มิโนมาดาม | 
59 | 
85 | 
| 2 | 
มิโนมาดาม | 
79 | 
105 | 
| 3 | 
มิโนมาดาม | 
69 | 
95 | 
| 4 | 
การ์เมล | 
94 | 
50 | 
 
 โปเกมอนที่ชื่อมิโนมาดามมีอยู่ ๓ แบบ แต่ละแบบมีชนิดต่างกัน พลังโจมตีและพลังป้องกันก็ต่างกันด้วย ดังนั้นทั้ง ๒ ตารางนี้จึงมีมิโนมาดามอยู่ ๓ แถว 
 เมื่อลองมารวมกันดู
print(pd.merge(chanit,phalang))
 จะได้
|   | 
สายพันธุ์ | 
ชนิด | 
พลังโจมตี | 
พลังป้องกัน | 
| 0 | 
มิโนมุจจิ | 
แมลง | 
29 | 
45 | 
| 1 | 
มิโนมาดาม | 
แมลง/พืช | 
59 | 
85 | 
| 2 | 
มิโนมาดาม | 
แมลง/พืช | 
79 | 
105 | 
| 3 | 
มิโนมาดาม | 
แมลง/พืช | 
69 | 
95 | 
| 4 | 
มิโนมาดาม | 
แมลง/ดิน | 
59 | 
85 | 
| 5 | 
มิโนมาดาม | 
แมลง/ดิน | 
79 | 
105 | 
| 6 | 
มิโนมาดาม | 
แมลง/ดิน | 
69 | 
95 | 
| 7 | 
มิโนมาดาม | 
แมลง/เหล็ก | 
59 | 
85 | 
| 8 | 
มิโนมาดาม | 
แมลง/เหล็ก | 
79 | 
105 | 
| 9 | 
มิโนมาดาม | 
แมลง/เหล็ก | 
69 | 
95 | 
| 10 | 
การ์เมล | 
แมลง/บิน | 
94 | 
50 | 
 
 ผลที่ได้พบว่ามีมิโดมาดาม ๙ แถว ซึ่งได้จากการแจกแจงตัวที่ซ้ำจากทั้งสองฝั่ง 
 ที่จริงเราอาจจะต้องการให้ข้อมูลทั้ง ๓ แถวนั้นแค่รวมกันโดยเรียงตามลำดับ แต่ในความเป็นจริง pd.merge จะไม่ได้มองแบบนั้น เมื่อเจอค่าที่ซ้ำกันมันไม่อาจรู้ได้ว่าเราต้องการให้แถวไหนเชื่อมกับแถวไหน ทำได้ก็เพียงแค่แจกแจงมันทั้งหมดเลย 
 หากต้องการจะแค่เอาคอลัมน์มาต่อกันจริงๆอาจลองใช้ concat จะเหมาะกว่า
print(pd.concat([chanit,phalang],axis=1))
 ได้
|   | 
สายพันธุ์ | 
ชนิด | 
สายพันธุ์ | 
พลังโจมตี | 
พลังป้องกัน | 
| 0 | 
มิโนมุจจิ | 
แมลง | 
มิโนมุจจิ | 
29 | 
45 | 
| 1 | 
มิโนมาดาม | 
แมลง/พืช | 
มิโนมาดาม | 
59 | 
85 | 
| 2 | 
มิโนมาดาม | 
แมลง/ดิน | 
มิโนมาดาม | 
79 | 
105 | 
| 3 | 
มิโนมาดาม | 
แมลง/เหล็ก | 
มิโนมาดาม | 
69 | 
95 | 
| 4 | 
การ์เมล | 
แมลง/บิน | 
การ์เมล | 
94 | 
50 | 
 
   รูปแบบของการเชื่อมโยง จากตัวอย่างที่ผ่านมา ข้อมูลในคอลัมน์ที่ใช้เชื่อมจากทั้ง ๒ ตารางนั้นส่วนใหญ่ต่างมีค่าเหมือนกันหมด แต่ในความเป็นจริงไม่จำเป็นต้องเป็นเช่นนั้น ในตารางหนึ่งอาจมีค่าที่ในอีกตารางไม่มีอยู่ 
 ตัวอย่าง มีตารางข้อมูลโปเกมอนสองตาราง อันนึงให้ข้อมูลส่วนสูงและน้ำหนัก อีกอันเป็นข้อมูลค่าพลังต่างๆ ทั้งสองอันนี้มีสมาชิกบางตัวไม่เหมือนกัน
sungnak = pd.DataFrame([
         ['โซนาโน',0.6,14.0],
         ['โซนานส์',1.3,28.5],
         ['ยุกิวาราชิ',0.7,16.8],
         ['โอนิโกริ',1.5,256.5]],
     columns=['สายพันธุ์','ส่วนสูง','น้ำหนัก'])
 phalang = pd.DataFrame([
         ['โซนาโน',23,48,95],
         ['ยุกิวาราชิ',50,50,50],
         ['โอนิโกริ',80,80,80],
         ['ยุกิเมะโนะโกะ',70,80,70]],
     columns=['สายพันธุ์','พลังโจมตี','พลังป้องกัน','HP'])
 print(sungnak)
 print(phalang)
 
 
 
 
 
 
 
 
  ได้
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
| 0 | 
โซนาโน | 
0.6 | 
14.0 | 
| 1 | 
โซนานส์ | 
1.3 | 
28.5 | 
| 2 | 
ยุกิวาราชิ | 
0.7 | 
16.8 | 
| 3 | 
โอนิโกริ | 
1.5 | 
256.5 | 
|   | 
สายพันธุ์ | 
พลังโจมตี | 
พลังป้องกัน | 
HP | 
| 0 | 
โซนาโน | 
23 | 
48 | 
95 | 
| 1 | 
ยุกิวาราชิ | 
50 | 
50 | 
50 | 
| 2 | 
โอนิโกริ | 
80 | 
80 | 
80 | 
| 3 | 
ยุกิเมะโนะโกะ | 
70 | 
80 | 
70 | 
 
 ลองเอามาเชื่อมกัน
print(pd.merge(sungnak,phalang))
 ผลที่ได้
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
พลังโจมตี | 
พลังป้องกัน | 
HP | 
| 0 | 
โซนาโน | 
0.6 | 
14.0 | 
23 | 
48 | 
95 | 
| 1 | 
ยุกิวาราชิ | 
0.7 | 
16.8 | 
50 | 
50 | 
50 | 
| 2 | 
โอนิโกริ | 
1.5 | 
256.5 | 
80 | 
80 | 
80 | 
 
 จะเห็นว่าข้อมูลที่ไม่ได้มีอยู่ในทั้งสองตารางเหมือนกันจะหายไปเลย ทำให้เหลือแค่ ๓ แถว 
 ทั้งนี้เป็นเพราะว่าโดยทั่วไปแล้วการเชื่อมโยงตารางถูกตั้งค่าเริ่มต้นให้เป็นแบบ inner นั่นคือเก็บเฉพาะที่มีเหมือนกันทั้งสองตาราง 
 แต่นอกจากนี้แล้วก็ยังมีอีก ๓ แบบ คือ
 left เก็บที่ตัวซ้ายมีทั้งหมดโดยไม่สนตัวขวา
 right เก็บที่ตัวขวามีทั้งหมดโดยไม่สนตัวซ้าย
 outer เก็บทั้งที่ตัวซ้ายมีและตัวขวามี 
 สามารถกำหนดว่าจะเชื่อมโยงแบบไหนโดยตั้งที่คีย์เวิร์ด how โดยที่ถ้าไม่ใส่จะเท่ากับ how='inner' 
 ตัวอย่าง
print(pd.merge(sungnak,phalang,how='outer'))
 ได้
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
พลังโจมตี | 
พลังป้องกัน | 
HP | 
| 0 | 
โซนาโน | 
0.6 | 
14.0 | 
23.0 | 
48.0 | 
95.0 | 
| 1 | 
โซนานส์ | 
1.3 | 
28.5 | 
NaN | 
NaN | 
NaN | 
| 2 | 
ยุกิวาราชิ | 
0.7 | 
16.8 | 
50.0 | 
50.0 | 
50.0 | 
| 3 | 
โอนิโกริ | 
1.5 | 
256.5 | 
80.0 | 
80.0 | 
80.0 | 
| 4 | 
ยุกิเมะโนะโกะ | 
NaN | 
NaN | 
70.0 | 
80.0 | 
70.0 | 
 
 จะเห็นว่าข้อมูลที่มีอยู่แค่ฝั่งใดฝั่งหนึ่งก็มาโผล่ในนี้ด้วย แต่ส่วนที่ขาดไปก็จะขึ้นเป็น NaN 
 นอกจากนี้หากลอง left กับ right ก็ออกมาในทำนองเดียวกัน
print('ซ้าย')
 print(pd.merge(sungnak,phalang,how='left'))
 print('ขวา')
 print(pd.merge(sungnak,phalang,how='right'))
 ได้
ซ้าย
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
พลังโจมตี | 
พลังป้องกัน | 
HP | 
| 0 | 
โซนาโน | 
0.6 | 
14.0 | 
23.0 | 
48.0 | 
95.0 | 
| 1 | 
โซนานส์ | 
1.3 | 
28.5 | 
NaN | 
NaN | 
NaN | 
| 2 | 
ยุกิวาราชิ | 
0.7 | 
16.8 | 
50.0 | 
50.0 | 
50.0 | 
| 3 | 
โอนิโกริ | 
1.5 | 
256.5 | 
80.0 | 
80.0 | 
80.0 | 
 ขวา
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
พลังโจมตี | 
พลังป้องกัน | 
HP | 
| 0 | 
โซนาโน | 
0.6 | 
14.0 | 
23 | 
48 | 
95 | 
| 1 | 
ยุกิวาราชิ | 
0.7 | 
16.8 | 
50 | 
50 | 
50 | 
| 2 | 
โอนิโกริ | 
1.5 | 
256.5 | 
80 | 
80 | 
80 | 
| 3 | 
ยุกิเมะโนะโกะ | 
NaN | 
NaN | 
70 | 
80 | 
70 | 
 
   เมื่อชื่อคอลัมน์ที่ต้องการเชื่อมไม่เหมือนกันในสองตาราง ไม่ใช่ว่าสองคอลัมน์จากสองตารางที่เอามาเชื่อมกันจะมีค่าชื่อคอลัมน์เหมือนกันเสมอไป ในกรณีที่ต่างกันแบบนี้จะต้องกำหนดชื่อคอลัมน์ที่ต้องการเชื่อมโดยใช้คีย์เวิร์ด left_on=ชื่อคอลัมน์ในตารางซ้าย และ right_on=ชื่อคอลัมน์ในตารางขวา 
 ตัวอย่าง
chue = pd.DataFrame([
         [480,'ยุกซี'],
         [481,'เอมริต'],
         [482,'อักนอม']],
     columns=['เลข','สายพันธุ์'])
 phalang = pd.DataFrame([
         [480,75,130],
         [481,105,105],
         [482,125,70]],
     columns=['หมายเลข','พลังโจมตี','พลังป้องกัน'])
 print(chue)
 print(phalang)
 
 
 
  ได้
|   | 
เลข | 
สายพันธุ์ | 
| 0 | 
480 | 
ยุกซี | 
| 1 | 
481 | 
เอมริต | 
| 2 | 
482 | 
อักนอม | 
|   | 
หมายเลข | 
พลังโจมตี | 
พลังป้องกัน | 
| 0 | 
480 | 
75 | 
130 | 
| 1 | 
481 | 
105 | 
105 | 
| 2 | 
482 | 
125 | 
70 | 
 
 ในที่นี้จะเชื่อมสองตารางซ้ายใช้ "เลข" ตารางขวาใช้ "หมายเลข"
print(pd.merge(chue,phalang,left_on='เลข',right_on='หมายเลข'))
 ผลที่ได้จะเห็นทั้งสองคอลัมน์อยู่พร้อมกันโดยมีค่าเท่ากัน
|   | 
เลข | 
สายพันธุ์ | 
หมายเลข | 
พลังโจมตี | 
พลังป้องกัน | 
| 0 | 
480 | 
ยุกซี | 
480 | 
75 | 
130 | 
| 1 | 
481 | 
เอมริต | 
481 | 
105 | 
105 | 
| 2 | 
482 | 
อักนอม | 
482 | 
125 | 
70 | 
 
   การใช้ดัชนีเป็นตัวเชื่อม ปกติแล้ว merge จะใช้คอลัมน์อันหนึ่งหรือจำนวนหนึ่งเป็นตัวเชื่อมโยงข้อมูลสองตารางเข้าด้วยกัน โดยที่ค่าดัชนีจะถูกเพิกเฉยและโยนทิ้งไปเลย 
 แต่หากต้องการใช้ดัชนีมาเป็นตัวเชื่อมก็ทำได้เช่นกัน โดยจะต้องใส่คีย์เวิร์ด left_index=1 หากต้องการให้ตัวซ้ายใช้ดัชนี และ right_index=1 หากต้องการให้ตัวขวาใช้ดัชนี 
 ส่วนอีกตัวที่ไม่ได้ใช้ดัชนีก็ให้กำหนดคอลัมน์ที่ต้องการเชื่อมด้วย left_on และ right_on 
 ตัวอย่าง
pokemon = pd.DataFrame([
         ['ชิโครีตา','พืช'],['ฮิโนอาราชิ','ไฟ'],['วานิโนโกะ','น้ำ'],
         ['คิโมริ','พืช'],['อาชาโม','ไฟ'],['มิซึโงโรว','น้ำ']],
     columns=['สายพันธุ์','ชนิด'],
     index=[152,155,158,252,255,258])
 phaechana = pd.DataFrame([
         ['เสมอ','แพ้','ชนะ'],
         ['ชนะ','เสมอ','แพ้'],
         ['แพ้','ชนะ','เสมอ'],
         ['แพ้','ชนะ','แพ้']],
     columns=['เจอพืช','เจอไฟ','เจอน้ำ'],
     index=['พืช','ไฟ','น้ำ','ดิน'])
 print(pokemon)
 print(phaechana)
 print(pd.merge(pokemon,phaechana,left_on='ชนิด',right_index=1))
 
 
 
 
 
 
  ได้
|   | 
สายพันธุ์ | 
ชนิด | 
| 152 | 
ชิโครีตา | 
พืช | 
| 155 | 
ฮิโนอาราชิ | 
ไฟ | 
| 158 | 
วานิโนโกะ | 
น้ำ | 
| 252 | 
คิโมริ | 
พืช | 
| 255 | 
อาชาโม | 
ไฟ | 
| 258 | 
มิซึโงโรว | 
น้ำ | 
|   | 
เจอพืช | 
เจอไฟ | 
เจอน้ำ | 
| พืช | 
เสมอ | 
แพ้ | 
ชนะ | 
| ไฟ | 
ชนะ | 
เสมอ | 
แพ้ | 
| น้ำ | 
แพ้ | 
ชนะ | 
เสมอ | 
| ดิน | 
แพ้ | 
ชนะ | 
แพ้ | 
|   | 
สายพันธุ์ | 
ชนิด | 
เจอพืช | 
เจอไฟ | 
เจอน้ำ | 
| 152 | 
ชิโครีตา | 
พืช | 
เสมอ | 
แพ้ | 
ชนะ | 
| 252 | 
คิโมริ | 
พืช | 
เสมอ | 
แพ้ | 
ชนะ | 
| 155 | 
ฮิโนอาราชิ | 
ไฟ | 
ชนะ | 
เสมอ | 
แพ้ | 
| 255 | 
อาชาโม | 
ไฟ | 
ชนะ | 
เสมอ | 
แพ้ | 
| 158 | 
วานิโนโกะ | 
น้ำ | 
แพ้ | 
ชนะ | 
เสมอ | 
| 258 | 
มิซึโงโรว | 
น้ำ | 
แพ้ | 
ชนะ | 
เสมอ | 
 
 แต่หากใช้ left_index=1 และ right_index=1 พร้อมกันผลที่ได้จะไม่ต่างจาก concat   
 สรุปคีย์เวิร์ดทั้งหมด
| คีย์เวิร์ด | 
ความหมาย | 
ค่าตั้งต้น | 
| how | 
วิธีการในการรวม | 
inner | 
| on | 
ชื่อคอลัมน์ที่ใช้เป็นตัวเชื่อม ไม่ใช้พร้อมกับ left_on และ right_on | 
คอลัมน์ที่ชื่อซ้ำกันทั้งหมด | 
| left_on | 
ชื่อคอลัมน์ของตารางซ้ายที่ใช้เป็นตัวเชื่อม ไม่ใช้พร้อมกับ on | 
  | 
| right_on | 
ชื่อคอลัมน์ของตารางขวาที่ใช้เป็นตัวเชื่อม ไม่ใช้พร้อมกับ on | 
  | 
| left_index | 
ใชัดัชนีของตารางซ้ายเป็นตัวเชื่อม | 
0 | 
| right_index | 
ใชัดัชนีของตารางขวาเป็นตัวเชื่อม | 
0 | 
| sort | 
จัดเรียงแถวในตารางตามค่าดัชนีด้วย หลังจากที่เชื่อมเสร็จ | 
0 | 
| suffixes | 
คำต่อท้ายหากชื่อคอลัมน์ที่ไม่ใช่ตัวเชื่อมเกิดซ้ำกัน | 
[_x,_y] | 
   การใช้เมธอด join นอกจากจะใช้ฟังก์ชัน pd.merge ในการเชื่อมตารางแล้ว ยังอาจใช้เมธอด join ของตัวเดตาเฟรมได้ วิธีการใช้ใกล้เคียงกัน เพียงแต่จะใช้เดตาเฟรมตัวหนึ่งเป็นฐานของเมธอด แล้วใช้อีกอันเป็นอาร์กิวเมนต์ 
 join ยังต่างจาก pd.merge ตรงที่ว่าหากไม่ระบุคีย์เวิร์ด on จะเป็นการเชื่อมโดยใช้ดัชนีเป็นตัวเชื่อม ต่างจาก pd.merge ที่ใช้คอลัมน์ที่ซ้ำ 
 ตัวอย่าง
sungnak = pd.DataFrame([
         ['เดียลกา',5.4,683.0],
         ['พาลเกีย',4.2,336.0],
         ['กิราทีนา',4.5,750.0]],
     columns=['สายพันธุ์','ส่วนสูง','น้ำหนัก'],
     index=[483,484,487])
 phalang = pd.DataFrame([
     [120,120],[120,100],[100,120]],
     columns=['พลังโจมตี','พลังป้องกัน'],
     index=[483,484,487])
 print(sungnak)
 print(phalang)
 print(sungnak.join(phalang))
 
 
 
  ได้
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
| 483 | 
เดียลกา | 
5.4 | 
683.0 | 
| 484 | 
พาลเกีย | 
4.2 | 
336.0 | 
| 487 | 
กิราทีนา | 
4.5 | 
750.0 | 
|   | 
พลังโจมตี | 
พลังป้องกัน | 
| 483 | 
120 | 
120 | 
| 484 | 
120 | 
100 | 
| 487 | 
100 | 
120 | 
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
พลังโจมตี | 
พลังป้องกัน | 
| 483 | 
เดียลกา | 
5.4 | 
683.0 | 
120 | 
120 | 
| 484 | 
พาลเกีย | 
4.2 | 
336.0 | 
120 | 
100 | 
| 487 | 
กิราทีนา | 
4.5 | 
750.0 | 
100 | 
120 | 
 
 ถ้าหากใส่คีย์เวิรืด on ลงไปจะเป็นการระบุคอลัมน์ของเดตาเฟรมที่เป็นเจ้าของเมธอด ส่วนเดตาเฟรมที่มาเติมนั้นยังไงก็ยังต้องเติมด้วยค่าดัชนี ไม่สามารถเชื่อมตามคอลัมน์ได้ 
 ตัวอย่าง ถ้าเรากำหนดเดตาเฟรมตัวที่มาเติมใหม่เป็น
phalang2 = pd.DataFrame([
     [120,120],[120,100],[100,120]],
     columns=['พลังโจมตี','พลังป้องกัน'],
     index=['เดียลกา','พาลเกีย','กิราทีนา'])
 print(phalang2)
 ได้
|   | 
พลังโจมตี | 
พลังป้องกัน | 
| เดียลกา | 
120 | 
120 | 
| พาลเกีย | 
120 | 
100 | 
| กิราทีนา | 
100 | 
120 | 
 
 ต่างจากตัวอย่างที่แล้วตรงที่ว่า index ไม่ใช่หมายเลขแต่กลายเป็นชื่อสายพันธุ์ของโปเกมอน แบบนี้จะต้องพิมพ์
print(sungnak.join(phalang2,on='สายพันธุ์'))
 ก็จะได้ผลเหมือนกับตัวอย่างที่แล้ว 
 และ join ไม่ได้ใช้แค่กับเดตาเฟรมแต่ยังใช้กับซีรีส์ได้ด้วย โดยจะเป็นการเพิ่มคอลัมน์ให้กับเดตาเฟรม อีกทั้งยังใส่หลายตัวพร้อมกันได้ด้วย โดยต้องใส่เป็นลิสต์ของเดตาเฟรมหรือซีรีส์ที่ต้องการเพิ่ม 
 ตัวอย่าง ลองสร้างซีรีส์ที่เก็บชนิดของโปเกมอน
chanit = pd.Series(['เหล็ก/มังกร','น้ำ/มังกร','ผี/มังกร'],
     index=[483,484,487],name='ชนิด')
 print(chanit)
 ได้
483    เหล็ก/มังกร
 484      น้ำ/มังกร
 487       ผี/มังกร
 Name: ชนิด, dtype: object
 จากนั้นก็นำมาใช้เชื่อมกับข้อมูลของสองตารางที่สร้างขึ้นมาก่อนหน้าด้วย เป็นการเชื่อมข้อมูล ๓ ตารางในทีเดียว
print(phalang.join([chanit,sungnak]))
 ได้
|   | 
พลังโจมตี | 
พลังป้องกัน | 
ชนิด | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
| 483 | 
120 | 
120 | 
เหล็ก/มังกร | 
เดียลกา | 
5.4 | 
683.0 | 
| 484 | 
120 | 
100 | 
น้ำ/มังกร | 
พาลเกีย | 
4.2 | 
336.0 | 
| 487 | 
100 | 
120 | 
ผี/มังกร | 
กิราทีนา | 
4.5 | 
750.0 | 
 
 สามารถใช้คีย์เวิร์ด how เพื่อกำหนดรูปแบบการเชื่อมโยงได้ เพียงแต่ว่าหากไม่กำหนดไว้ค่าเริ่มต้นจะเป็น left นั่นคือยึดเอาเดตาเฟรามที่เป็นฐานของเมธอดเป็นหลัก 
 นอกจากนี้ยังมีข้อแตกต่างเล็กๆน้อยๆอีกเช่น คีย์เวิร์ด suffixes ใน pd.merge นั้นจะเทียบเท่ากับคีย์เวิร์ด lsuffix กับ rsuffix ของ join กล่าวคือ join ใช้คีย์เวิร์ดแยก ๒ ตัวแทนที่จะรวมกันเป็นลิสต์ 
 ตัวอย่าง
pokemon1 = pd.DataFrame([
         ['มานิวลา',1.1,34.0,'มาร'],
         ['จิบะคอยล์',1.2,180.0,'ไฟฟ้า'],
         ['เบโรเบลต์',1.7,140.0,'ธรรมดา'],
         ['โดไซดอน',2.4,282.8,'ดิน']],
     columns=['สายพันธุ์','ส่วนสูง','น้ำหนัก','ชนิด'],
     index=[461,462,463,464])
 pokemon2 = pd.DataFrame([
         ['น้ำแข็ง',120,65],
         ['เหล็ก',70,115],
         ['หิน',140,130],
         ['พืช',100,125]],
     columns=['ชนิด','พลังโจมตี','พลังป้องกัน'],
     index=[461,462,464,465])
 print(pokemon1)
 print(pokemon2)
 print(pokemon1.join(pokemon2,lsuffix=' 1',rsuffix=' 2'))
 
 
 
 
 
 
 
 
  ได้
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
ชนิด | 
| 461 | 
มานิวลา | 
1.1 | 
34.0 | 
มาร | 
| 462 | 
จิบะคอยล์ | 
1.2 | 
180.0 | 
ไฟฟ้า | 
| 463 | 
เบโรเบลต์ | 
1.7 | 
140.0 | 
ธรรมดา | 
| 464 | 
โดไซดอน | 
2.4 | 
282.8 | 
ดิน | 
|   | 
ชนิด | 
พลังโจมตี | 
พลังป้องกัน | 
| 461 | 
น้ำแข็ง | 
120 | 
65 | 
| 462 | 
เหล็ก | 
70 | 
115 | 
| 464 | 
หิน | 
140 | 
130 | 
| 465 | 
พืช | 
100 | 
125 | 
|   | 
สายพันธุ์ | 
ส่วนสูง | 
น้ำหนัก | 
ชนิด 1 | 
ชนิด 2 | 
พลังโจมตี | 
พลังป้องกัน | 
| 461 | 
มานิวลา | 
1.1 | 
34.0 | 
มาร | 
น้ำแข็ง | 
120.0 | 
65.0 | 
| 462 | 
จิบะคอยล์ | 
1.2 | 
180.0 | 
ไฟฟ้า | 
เหล็ก | 
70.0 | 
115.0 | 
| 463 | 
เบโรเบลต์ | 
1.7 | 
140.0 | 
ธรรมดา | 
NaN | 
NaN | 
NaN | 
| 464 | 
โดไซดอน | 
2.4 | 
282.8 | 
ดิน | 
หิน | 
140.0 | 
130.0 | 
 
 จะเห็นว่า 465 ซึ่งไม่มีในตารางซ้ายถูกตัดทิ้งไป แต่ 463 ซึ่งไม่มีในตารางขวาก็ยังคงถูกเก็บไว้ ส่วน "ชนิด" ซึ่งเป็นชื่อคอลัมน์ที่ซ้ำกันก็ถูกเติม 1 และ 2 ต่อท้าย    
อ้างอิง