มีหลากหลายวิธีในการนำข้อมูลที่มีอยู่ในซีรีส์หรือเดตาเฟรมสองอันขึ้นไปมารวมเข้าด้วยกัน ในบทนี้จะพูดถึงวิธีการรวมโดยใช้ฟังก์ชัน pd.concat และเมธอด append
    การเอาซีรีส์มาต่อกัน เมื่อมีซีรีส์สองอันขึ้นไปแล้วจะเอามารวมกันอาจทำได้โดยใช้ฟังก์ชัน pd.concat โดยใส่ลิสต์ของซีรีส์ที่ต้องการรวมลงไป 
 ตัวอย่าง สร้างซีรีส์ขึ้นมา ๒ อัน
import pandas as pd
 pokemon1 = pd.Series(['โป๊ปโป','พีเจียน','พีจ็อต'])
 pokemon2 = pd.Series(['โอนิสึซึเมะ','โอนิดริล'])
 print(pokemon1)
 print(pokemon2)
  
  
  
  
  
  ได้
0     โป๊ปโป
 1    พีเจียน
 2     พีจ็อต
 dtype: object
 0    โอนิสึซึเมะ
 1       โอนิดริล
 dtype: object
 จากนั้นใช้ concat
print(pd.concat([pokemon1,pokemon2]))
 ได้
0         โป๊ปโป
 1        พีเจียน
 2         พีจ็อต
 0    โอนิสึซึเมะ
 1       โอนิดริล
 dtype: object
 ซีรีส์จะถูกนำมาต่อกัน แต่ก็จะเห็นว่าดัชนีมีการซ้ำกันเกิดขึ้น โดยยึดตามดัชนีเดิมโดยไม่มีการเปลี่ยนให้อัตโนมัติ 
 หากต้องการให้เวลาที่ต่อกันแล้วลืมดัชนีเดิมทิ้งไปเลยก็ให้ใส่ ignore_index=1 เท่านี้ดัชนีก็จะจัดเรียงใหม่ไล่ตั้งแต่ 0 ไม่ว่าจะเคยเป็นอะไรมาก่อน
print(pd.concat([pokemon1,pokemon2],ignore_index=1))
 ได้
0         โป๊ปโป
 1        พีเจียน
 2         พีจ็อต
 3    โอนิสึซึเมะ
 4       โอนิดริล
 dtype: object
   การรวมซีรีส์เป็นเดตาเฟรม การรวมซีรีส์นั้นนอกจากจะเอามาต่อกันให้เป็นสายยาวขึ้นแล้วยังสามารถรวมกันในลักษณะที่ใช้ซีรีส์อันหนึ่งเป็นคอลัมน์หนึ่งเพื่อสร้างเดตาเฟรมขึ้นมา 
 ในกรณีแบบนี้ให้ใส่ axis=1 แล้วก็ควรจะเป็นซีรีส์ที่มีการตั้งชื่อไว้ด้วย แล้วชื่อนั้นจะกลายมาเป็นชื่อคอลัมน์ ถ้าไม่ได้ตั้งก็จะถูกตั้งเองเป็นตัวเลข
ตัวอย่าง
saiphan = pd.Series(['อูริมู','อิโนมู','แมมมู'],name='สายพันธุ์')
 mailek = pd.Series([220,221,473],name='หมายเลข')
 print(saiphan)
 print(mailek)
 ได้
0    อูริมู
 1    อิโนมู
 2     แมมมู
 Name: สายพันธุ์, dtype: object
 0    220
 1    221
 2    473
 Name: หมายเลข, dtype: int64
  
  
  
   นำมา concat
print(pd.concat([saiphan,mailek],axis=1))
 ได้
|  | สายพันธุ์ | หมายเลข | 
| 0 | อูริมู | 220 | 
| 1 | อิโนมู | 221 | 
| 2 | แมมมู | 473 | 
 
 การรวมกันในกรณี axis=1 นี้จะยึดตามเลขดัชนี คือรวมแถวที่เลขดัชนีเหมือนกันเข้าด้วยกัน ถ้าดัชนีของทั้ง ๒ ซีรีส์ต่างกันผลที่ได้ก็จะมี NaN 
 ตัวอย่างเช่น
saiphan = pd.Series(['โนคจจิ','ฮารีเซน','ทสึโบะทสึโบะ'],index=[206,211,213],name='สายพันธุ์')
 chanit = pd.Series(['ธรรมดา','น้ำ/พิษ','แมลง/ต่อสู้'],index=[206,211,214],name='ชนิด')
 print(saiphan)
 print(chanit)
 print(pd.concat([saiphan,chanit],axis=1))
  
  
  
  
  
  
   ได้
206          โนคจจิ
 211         ฮารีเซน
 213    ทสึโบะทสึโบะ
 Name: สายพันธุ์, dtype: object
 206         ธรรมดา
 211        น้ำ/พิษ
 214    แมลง/ต่อสู้
 Name: ชนิด, dtype: object
|  | สายพันธุ์ | ชนิด | 
| 206 | โนคจจิ | ธรรมดา | 
| 211 | ฮารีเซน | น้ำ/พิษ | 
| 213 | ทสึโบะทสึโบะ | NaN | 
| 214 | NaN | แมลง/ต่อสู้ | 
 เช่นเดียวกับซีรีส์ เมื่อจะเอาเดตาเฟรมสองอันขึ้นไปมารวมกันก็สามารถใช้ pd.concat โดยใส่ลิสต์ของเดตาเฟรมที่ต้องการรวมลงไป 
 ปกติแล้วถ้าไม่ได้กำหนดคีย์เวิร์ด axis หรือกำหนด axis=0 จะเป็นการรวมในแนวตั้ง คือรวมที่มีคอลัมน์ชื่อเหมือนกันแต่ดัชนีต่างกัน ผลที่ได้จะได้เดตาเฟรมที่ต่อกันเป็นแถวยาวมีจำนวนดัชนีเท่ากับเดตาเฟรมทั้งหมดรวมกัน 
 ถ้ากำหนด axis=1 จะเป็นการรวมกันในแนวนอน คือรวมที่มีชื่อดัชนีเหมือนกันแต่เป็นคนละชื่อคอลัมน์ แล้วก็จะได้เดตาเฟรมที่มีจำนวนคอลัมน์มากขึ้น 
 ๒ แบบนี้มีหลักการเหมือนกันเพียงแค่กลับแนวตั้งแนวนอนกัน ดังนั้นในที่นี้จะยกตัวอย่างแค่กรณีแนวตั้ง 
 ตัวอย่าง สร้างเดตาเฟรมเก็บข้อมูลโปเกมอนขึ้นมา ๓ ตาราง
pokemon1 = pd.DataFrame([
         ['ธรรมดา',55,55,55],
         ['น้ำ',130,65,65],
         ['ไฟฟ้า',65,65,130],
         ['ไฟ',65,130,65]],
     index=['อีวุย','เชาเวอร์ส','ธันเดอร์ส','บูสเตอร์'],
     columns=['ชนิด','HP','พลังโจมตี','ความไว'])
 pokemon2 = pd.DataFrame([
         ['พลังจิต',65,60,110],
         ['มาร',95,110,65]],
     index=['เอย์ฟี','แบล็กกี'],
     columns=['ชนิด','HP','พลังป้องกัน','ความไว'])
 pokemon3 = pd.DataFrame({
         'ชนิด':['พืช','น้ำแข็ง'],
         'HP':[65,65],
         'พลังโจมตี':[110,60],
         'พลังป้องกัน':[130,110]},
     index=['ลีเฟีย','เกลเซีย'])
 print(pokemon1)
 print(pokemon2)
 print(pokemon3)
  
  
  
  
  
  
  
  
   ได้
|  | ชนิด | HP | พลังโจมตี | ความไว | 
| อีวุย | ธรรมดา | 55 | 55 | 55 | 
| เชาเวอร์ส | น้ำ | 130 | 65 | 65 | 
| ธันเดอร์ส | ไฟฟ้า | 65 | 65 | 130 | 
| บูสเตอร์ | ไฟ | 65 | 130 | 65 | 
|  | ชนิด | HP | พลังป้องกัน | ความไว | 
| เอย์ฟี | พลังจิต | 65 | 60 | 110 | 
| แบล็กกี | มาร | 95 | 110 | 65 | 
|  | HP | ชนิด | พลังป้องกัน | พลังโจมตี | 
| ลีเฟีย | 65 | พืช | 130 | 110 | 
| เกลเซีย | 65 | น้ำแข็ง | 110 | 60 | 
 
 นำมารวมกัน
print(pd.concat([pokemon1,pokemon2,pokemon3]))
 ได้
|  | HP | ความไว | ชนิด | พลังป้องกัน | พลังโจมตี | 
| อีวุย | 55 | 55.0 | ธรรมดา | NaN | 55.0 | 
| เชาเวอร์ส | 130 | 65.0 | น้ำ | NaN | 65.0 | 
| ธันเดอร์ส | 65 | 130.0 | ไฟฟ้า | NaN | 65.0 | 
| บูสเตอร์ | 65 | 65.0 | ไฟ | NaN | 130.0 | 
| เอย์ฟี | 65 | 110.0 | พลังจิต | 60.0 | NaN | 
| แบล็กกี | 95 | 65.0 | มาร | 110.0 | NaN | 
| ลีเฟีย | 65 | NaN | พืช | 130.0 | 110.0 | 
| เกลเซีย | 65 | NaN | น้ำแข็ง | 110.0 | 60.0 | 
 
 จะเห็นว่าทั้ง ๓ เดตาเฟรมก่อนรวมมีคอลัมน์ที่ทั้งเหมือนกันและต่างกัน เมื่อรวมกันแล้วคอลัมน์ที่ไม่มีจะได้ค่าเป็น NaN และลำดับของคอลัมน์ก็ถูกจัดเรียงให้ใหม่โดยอัตโนมัติไม่ได้เป็นไปตามที่เรียงตอนแรกด้วย 
 บางครั้งเราอาจไม่ได้ต้องการทุกคอลัมน์แต่อาจต้องการเหลือแค่บางคอลัมน์ กรณีแบบนี้อาจใส่คีย์เวิร์ด join_axes โดยใส่ค่าเป็นซีรีส์ของชื่อคอลัมน์ที่ต้องการ เช่น
c = pd.Series(['พลังโจมตี','พลังป้องกัน','ความไว'])
 print(pd.concat([pokemon1,pokemon2,pokemon3],join_axes=[c]))
 ได้
|  | พลังโจมตี | พลังป้องกัน | ความไว | 
| อีวุย | 55.0 | NaN | 55.0 | 
| เชาเวอร์ส | 65.0 | NaN | 65.0 | 
| ธันเดอร์ส | 65.0 | NaN | 130.0 | 
| บูสเตอร์ | 130.0 | NaN | 65.0 | 
| เอย์ฟี | NaN | 60.0 | 110.0 | 
| แบล็กกี | NaN | 110.0 | 65.0 | 
| ลีเฟีย | 110.0 | 130.0 | NaN | 
| เกลเซีย | 60.0 | 110.0 | NaN | 
 
 ให้ระวังว่าค่าที่ต้องใส่ต้องเป็นลิสต์แม้ว่าจะมีอยู่แค่ตัวเดียวก็ตาม (ในที่นี้คือเป็น join_axes=[c] ไม่ใช่ join_axes=c) ที่จริงแล้วคีย์เวิร์ดนี้ทำไว้รองรับกรณีที่เป็นแบบคอลัมน์หลายแถว ซึ่งในกรณีแบบนั้นจะต้องใส่ซีรีส์ตามจำนวนเท่านั้น 
 ถ้าต้องการใช้คอลัมน์ของเดตาเฟรมสักอันก็อาจใช้ได้โดยใช้ เดตาเฟรม.columns เช่น
print(pd.concat([pokemon1,pokemon2,pokemon3],join_axes=[pokemon3.columns]))
 ได้
|  | HP | ชนิด | พลังป้องกัน | พลังโจมตี | 
| อีวุย | 55 | ธรรมดา | NaN | 55.0 | 
| เชาเวอร์ส | 130 | น้ำ | NaN | 65.0 | 
| ธันเดอร์ส | 65 | ไฟฟ้า | NaN | 65.0 | 
| บูสเตอร์ | 65 | ไฟ | NaN | 130.0 | 
| เอย์ฟี | 65 | พลังจิต | 60.0 | NaN | 
| แบล็กกี | 95 | มาร | 110.0 | NaN | 
| ลีเฟีย | 65 | พืช | 130.0 | 110.0 | 
| เกลเซีย | 65 | น้ำแข็ง | 110.0 | 60.0 | 
 
 นอกจากนี้กรณีที่ต้องการเก็บเฉพาะคอลัมน์ที่ทุกเดตาเฟรมต่างก็มีเหมือนกันหมดก็อาจใส่คีย์เวิร์ด join เพิ่มลงไป โดยใส่เป็น join='inner' 
 ปกติแล้วถ้าไม่ใส่คีย์เวิร์ดนี้ลงไปจะหมายถึง join='outer' หมายถึงใช้ทุกคอลัมน์ที่มีจากทุกเดตาเฟรม แต่ถ้า inner ก็จะหมายถึงใช้เฉพาะคอลัมน์ที่มีในทุกอัน ตัวอย่างเช่น
print(pd.concat([pokemon1,pokemon2,pokemon3],join='inner'))
 ได้
|  | HP | ชนิด | 
| อีวุย | 55 | ธรรมดา | 
| เชาเวอร์ส | 130 | น้ำ | 
| ธันเดอร์ส | 65 | ไฟฟ้า | 
| บูสเตอร์ | 65 | ไฟ | 
| เอย์ฟี | 65 | พลังจิต | 
| แบล็กกี | 95 | มาร | 
| ลีเฟีย | 65 | พืช | 
| เกลเซีย | 65 | น้ำแข็ง | 
 
   การรวมแล้วทำเป็นดัชนีซ้อน ปกติเวลาที่ใช้ concat เพื่อต่อแถวเดตาเฟรมหากดัชนีมีตัวที่ซ้ำกันผลที่ได้ก็จะเป็นดัชนีที่ซ้ำกัน ซึ่งอาจแก้ไขได้ด้วยการใช้คีย์เวิร์ด ignore_index 
 แต่วิธีนั้นจะทำให้สูญเสียดัชนีเดิมหมด ที่จริงแล้วมีวิธีที่ดีกว่านั้นแม้ว่าจะทำให้ซับซ้อนขึ้นสักหน่อย นั่นคือการเพิ่มข้อมูลที่ว่าข้อมูลแถวนั้นมาจากเดตาเฟรมตัวไหนลงไปใส่เป็นดัชนีซ้อนลงไป 
 สามารถทำได้โดยใส่คีย์เวิร์ด keys แล้วตามด้วยลิสต์ของค่าดัชนีที่จะใช้แทนแต่ละตาราง 
 ตัวอย่าง ลองสร้างตารางข้อมูลโปเกมอนตัวหลักในแต่ละภาค
pokemon1 = pd.DataFrame([
     ['ฟุชิงิดาเนะ','พืช'],['ฮิโตคาเงะ','ไฟ'],['เซนิงาเมะ','น้ำ']],
     index=[1,4,7],columns=['สายพันธุ์','ชนิด'])
 pokemon2 = pd.DataFrame([
     ['ชิโครีตา','พืช'],['ฮิโนอาราชิ','ไฟ'],['วานิโนโกะ','น้ำ']],
     index=[1,4,7],columns=['สายพันธุ์','ชนิด'])
 pokemon3 = pd.DataFrame([
     ['คิโมริ','พืช'],['อาชาโม','ไฟ'],['มิซึโงโรว','น้ำ']],
     index=[1,4,7],columns=['สายพันธุ์','ชนิด'])
 print(pokemon1)
 print(pokemon2)
 print(pokemon3)
  
  
  
  
  
  
  
  
  
  ได้
|  | สายพันธุ์ | ชนิด | 
| 1 | ฟุชิงิดาเนะ | พืช | 
| 4 | ฮิโตคาเงะ | ไฟ | 
| 7 | เซนิงาเมะ | น้ำ | 
|  | สายพันธุ์ | ชนิด | 
| 1 | ชิโครีตา | พืช | 
| 4 | ฮิโนอาราชิ | ไฟ | 
| 7 | วานิโนโกะ | น้ำ | 
|  | สายพันธุ์ | ชนิด | 
| 1 | คิโมริ | พืช | 
| 4 | อาชาโม | ไฟ | 
| 7 | มิซึโงโรว | น้ำ | 
 
 นำมารวมกันให้เป็นดัชนีซ้อนกัน กำหนดดัชนีเป็นตัวเลขลำดับภาค
print(pd.concat([pokemon1,pokemon2,pokemon3],keys=[1,2,3]))
 ได้
|  |  | สายพันธุ์ | ชนิด | 
| 1 | 1 | ฟุชิงิดาเนะ | พืช | 
| 4 | ฮิโตคาเงะ | ไฟ | 
| 7 | เซนิงาเมะ | น้ำ | 
| 2 | 1 | ชิโครีตา | พืช | 
| 4 | ฮิโนอาราชิ | ไฟ | 
| 7 | วานิโนโกะ | น้ำ | 
| 3 | 1 | คิโมริ | พืช | 
| 4 | อาชาโม | ไฟ | 
| 7 | มิซึโงโรว | น้ำ | 
 
 นอกจากนี้มีอีกวิธีในการรวมให้ได้ดัชนีซ้อนในลักษณะแบบนี้โดยไม่ใช้คีย์เวิร์ด keys นั่นคือแทนที่จะใส่ค่าในรูปลิสต์ก็ใส่ในรูปดิกชันนารีโดยที่มีคีย์เป็นค่าดัชนีที่ต้องการ
เช่น หากต้องการผลเหมือนตัวอย่างข้างต้นก็พิมพ์
print(pd.concat({1:pokemon1,2:pokemon2,3:pokemon3}))
   การต่อขยายซีรีส์ หากมีซีรีส์อยู่อันหนึ่งแล้วต้องการเอาข้อมูลจากซีรีส์อีกอันมาใส่สามารถใช้เมธอด append ได้ 
 เพียงแต่ว่าเมธอด appand นี้ว่ากันตามจริงแล้วก็เหมือนเป็นฟังก์ชัน np.concat ที่เขียนในรูปแบบเมธอดของเดตาเฟรมอันหนึ่ง เพราะการ "เอาอันหนึ่งมาต่อกับอีกอัน" กับ "เอาสองอันมาต่อกัน" ก็คือสิ่งเดียวกัน 
 ต่างกันก็ตรงที่ว่า append จะใช้อันหนึ่งเป็นฐานของเมธอด และอันที่เหลือเป็นอาร์กิวเมนต์ 
 ตัวอย่างการใช้
pokemon1 = pd.Series(['อูปา','นูโอ'],index=[194,195])
 pokemon2 = pd.Series(['ฮัสโบ','ฮาสึเบรโร','รูนปัปปะ'],index=[270,271,272])
 pokemon3 = pd.Series(['บุยเซล','โฟลเซล'],index=[418,419])
 print(pokemon1.append([pokemon2,pokemon3]))
  
  
  
  
  
  
  
  ได้
194         อูปา
 195         นูโอ
 270        ฮัสโบ
 271    ฮาสึเบรโร
 272     รูนปัปปะ
 418       บุยเซล
 419       โฟลเซล
 dtype: object
 append ไม่ได้ทำการเปลี่ยนแปลงใดๆกับเดตาเฟรมที่เป็นฐาน แค่จะทำการคืนค่าเดตาเฟรมตัวใหม่ที่อยู่ในสภาพหลังต่อขยายมาแล้วเท่านั้น    
การต่อขยายเดตาเฟรม เช่นเดียวกับซีรีส์ เดตาเฟรมก็มีเมธอด append ไว้สำหรับเอาเดตาเฟรมตัวอื่นๆมาต่อให้กับเดตาเฟรมตัวหนึ่ง 
 ตัวอย่าง
pokemon1 = pd.DataFrame([
         ['ดัมเบอร์','เหล็ก/พลังจิต',0.6,95.2],
         ['เมทัง','เหล็ก/พลังจิต',0.6,95.2],
         ['เมทากรอส','เหล็ก/พลังจิต',1.6,550.0]],
     index=[374,375,376],
     columns=['สายพันธุ์','ชนิด','ส่วนสูง','น้ำหนัก'])
 pokemon2 = pd.DataFrame([
         ['ทัตสึเบย์','มังกร',0.6,42.1],
         ['โคโมรู','มังกร',1.1,110.5],
         ['โบมันเดอร์','มังกร',1.5,102.6]],
     index=[371,372,373],
     columns=['สายพันธุ์','ชนิด','ส่วนสูง','น้ำหนัก'])
 print(pokemon1)
 print(pokemon2)
 print(pokemon1.append(pokemon2))
  
  
  
  
  
  
  ได้
|  | สายพันธุ์ | ชนิด | ส่วนสูง | น้ำหนัก | 
| 374 | ดัมเบอร์ | เหล็ก/พลังจิต | 0.6 | 95.2 | 
| 375 | เมทัง | เหล็ก/พลังจิต | 0.6 | 95.2 | 
| 376 | เมทากรอส | เหล็ก/พลังจิต | 1.6 | 550.0 | 
|  | สายพันธุ์ | ชนิด | ส่วนสูง | น้ำหนัก | 
| 371 | ทัตสึเบย์ | มังกร | 0.6 | 42.1 | 
| 372 | โคโมรู | มังกร | 1.1 | 110.5 | 
| 373 | โบมันเดอร์ | มังกร | 1.5 | 102.6 | 
|  | สายพันธุ์ | ชนิด | ส่วนสูง | น้ำหนัก | 
| 374 | ดัมเบอร์ | เหล็ก/พลังจิต | 0.6 | 95.2 | 
| 375 | เมทัง | เหล็ก/พลังจิต | 0.6 | 95.2 | 
| 376 | เมทากรอส | เหล็ก/พลังจิต | 1.6 | 550.0 | 
| 371 | ทัตสึเบย์ | มังกร | 0.6 | 42.1 | 
| 372 | โคโมรู | มังกร | 1.1 | 110.5 | 
| 373 | โบมันเดอร์ | มังกร | 1.5 | 102.6 | 
 
 append นั้นในกรณีที่ใช้กับเดตาเฟรมนอกจากใช้ตัวที่ต่อเป็นเดตาเฟรมแล้วก็ยังอาจใช้ซีรีส์มาเป็นตัวต่อได้อีกด้วย ซึ่งถ้าเป็น concat จะใช้แบบนี้ไม่ได้ โดยที่ซีรีส์ที่จะใช้นั้นต้องมีจำนวนแถวเท่ากับจำนวนคอลัมน์ของเดตาเฟรมพอดี 
 ตัวอย่าง
pokemon3 = pd.Series(['เลิฟคัส','น้ำ',0.6,8.7],
                      index=['สายพันธุ์','ชนิด','ส่วนสูง','น้ำหนัก'],
                      name=370)
 print(pokemon1.append(pokemon3))
  
  
  
  
  ได้
|  | สายพันธุ์ | ชนิด | ส่วนสูง | น้ำหนัก | 
| 374 | ดัมเบอร์ | เหล็ก/พลังจิต | 0.6 | 95.2 | 
| 375 | เมทัง | เหล็ก/พลังจิต | 0.6 | 95.2 | 
| 376 | เมทากรอส | เหล็ก/พลังจิต | 1.6 | 550.0 | 
| 370 | เลิฟคัส | น้ำ | 0.6 | 8.7 | 
 
   อ้างอิง