Data Analyst › pandas

pivot_table และ melt

ประมาณ 30 นาที

เป้าหมายของบท

  • สร้างตารางสรุปแบบ "กว้าง" ด้วย pivot_table (values/index/columns/aggfunc/fill_value)
  • แปลงข้อมูลจาก "กว้าง" เป็น "ยาว" ด้วย melt
  • รู้ว่า pivot_table ที่ใส่ aggfunc เป็น list จะได้คอลัมน์ซ้อนกัน (MultiIndex) ที่ดึงค่ายากกว่าปกติ

สร้างตารางสรุปแบบ “กว้าง” ด้วย pivot_table

orders.pivot_table(values='order_id', index='status', columns='payment_method', aggfunc='count', fill_value=0)
พารามิเตอร์ ความหมาย
values คอลัมน์ที่จะเอาไปสรุป
index คอลัมน์ที่จะเป็น “แถว” ของตารางผลลัพธ์
columns คอลัมน์ที่จะเป็น “คอลัมน์” ของตารางผลลัพธ์ (ไม่ใส่ก็ได้ ถ้าอยากได้แค่ 1 มิติ)
aggfunc ฟังก์ชันสรุป ('count', 'sum', 'mean', …)
fill_value ค่าที่ใส่แทนช่องที่ไม่มีข้อมูล (ปกติจะเป็นค่าว่าง)

pivot_table เหมาะมากเมื่ออยากดูข้อมูล 2 มิติ (แถว×คอลัมน์) พร้อมกันในตารางเดียว — ต่างจาก groupby ที่ให้ผลเป็นรูปแบบ “ยาว” เสมอ

ระวัง: ถ้าใส่ aggfunc เป็น list มากกว่า 1 ฟังก์ชัน (เช่น ['min', 'max']) จะได้คอลัมน์ซ้อนกัน (MultiIndex) ที่ดึงค่ายากกว่าปกติมาก ถ้าต้องการหลายฟังก์ชันพร้อมกัน ใช้ .agg() แบบตั้งชื่อเอง (บทที่ 4) แทน

แปลงกว้างเป็นยาวด้วย melt

products[['product_id', 'price', 'cost']].melt(id_vars='product_id')

melt คือการย้อนกลับของ pivot_table — เอาหลายคอลัมน์ (price, cost) มาแปลงเป็นแถว โดยมี id_vars เป็นคอลัมน์ที่ยังคงอยู่เดิม (บอกว่าแต่ละแถวเป็นของอะไร) ผลลัพธ์จะมีคอลัมน์ variable (ชื่อคอลัมน์เดิม) กับ value (ค่าเดิม) — ตั้งชื่อเองได้ด้วย var_name=/value_name=

ระวัง: ถ้าลืมใส่ id_vars จะเอาทุกคอลัมน์ไปแปลงเป็นแถวหมด ไม่เหลือคอลัมน์บอกที่มาของแต่ละแถวเลย

ตัวอย่างแก้โจทย์

กด "ขั้นต่อไป" ทีละขั้น ลองรันและแก้โค้ดในแต่ละขั้นได้

จำนวนออเดอร์แต่ละคู่ (สถานะ, วิธีจ่ายเงิน) แบบตารางกว้าง

อยากเห็นจำนวนออเดอร์แยกตามสถานะและวิธีจ่ายเงินพร้อมกันในตารางเดียว

  1. pivot_table จัดวางค่าหนึ่งคอลัมน์เป็น index (แถว) อีกคอลัมน์เป็น columns (คอลัมน์) ถ้าบางคู่ไม่มีข้อมูลเลย ช่องนั้นจะเป็นค่าว่าง

    Python

แปลงคอลัมน์ price/cost ให้เป็นแถว (long format) ด้วย melt

บางครั้งอยากได้ข้อมูลแบบ "ยาว" (แต่ละแถวคือ 1 ค่า) แทนที่จะเป็น "กว้าง" (แต่ละคอลัมน์คือ 1 ตัวชี้วัด)

  1. ดูตารางแบบกว้างก่อน (product_id, price, cost อยู่คนละคอลัมน์)

    Python

เติมช่องว่าง

แทน ___ ด้วยโค้ดที่ถูกต้อง แล้วกดตรวจคำตอบ

ยังไม่ได้ทำ

ราคาเฉลี่ยของสินค้าแต่ละหมวด (ปัดเป็นจำนวนเต็ม) แบบ pivot_table เก็บไว้ในตัวแปร result เติม ___ ให้ครบ

แบบฝึกท้ายบท

บทนี้จะนับว่าเสร็จเมื่อผ่านข้อพื้นฐานและประยุกต์ครบ ข้อท้าทายได้ดาวเพิ่ม

🟢 พื้นฐาน

🟢 พื้นฐานยังไม่ได้ทำ

จำนวนสินค้าในแต่ละหมวด (pivot_table, aggfunc='count') เก็บไว้ในตัวแปร result

🟢 พื้นฐานยังไม่ได้ทำ

จำนวนออเดอร์ในแต่ละคู่ (สถานะ, วิธีจ่ายเงิน) แบบตารางกว้าง (fill_value=0) เก็บไว้ในตัวแปร result

🟢 พื้นฐานยังไม่ได้ทำ

แปลงคอลัมน์ price กับ cost ของ 2 สินค้าแรก (product_id, price, cost) ให้เป็น long format เก็บไว้ในตัวแปร result

🟢 พื้นฐานยังไม่ได้ทำ

ราคาเฉลี่ย (ปัดเป็นจำนวนเต็ม) ของสินค้าแต่ละหมวด (pivot_table) เก็บไว้ในตัวแปร result

🟡 ประยุกต์

🟡 ประยุกต์ยังไม่ได้ทำ

รายได้รวม (completed, quantity×unit_price) แยกตามหมวดสินค้า×สถานะ แบบตารางกว้าง (fill_value=0, ปัดเป็นจำนวนเต็ม) เก็บไว้ในตัวแปร result

🟡 ประยุกต์ยังไม่ได้ทำ

ส่วนลดเฉลี่ย (ปัด 1 ตำแหน่ง) แยกตามวิธีจ่ายเงิน×ปีของออเดอร์ แบบตารางกว้าง เก็บไว้ในตัวแปร result

🟡 ประยุกต์ยังไม่ได้ทำ

แปลง price/cost ของสินค้าทั้งหมดเป็น long format (id_vars=category) แล้วรวมยอด cost ต่อหมวด เก็บไว้ในตัวแปร result

🔴 ท้าทาย

🔴 ท้าทายยังไม่ได้ทำ

จากตาราง (สถานะ×วิธีจ่ายเงิน) ในตัวอย่าง x1 คำนวณสัดส่วน % ของแต่ละช่องเทียบกับผลรวมของแถวนั้น (ปัด 1 ตำแหน่ง) เก็บไว้ในตัวแปร result

Quiz

1. pivot_table กับ groupby ต่างกันยังไง
2. melt ทำอะไร
3. aggfunc เป็น list (เช่น ['min','max']) ให้ผลลัพธ์แบบไหน

สรุป

  • pivot_table สร้างตารางสรุปแบบกว้าง (index=แถว, columns=คอลัมน์, values=ค่า, aggfunc=วิธีสรุป)
  • melt แปลงข้อมูลจากกว้างเป็นยาว เป็นการย้อนกลับของ pivot_table
  • aggfunc เป็น list ทำให้ได้คอลัมน์ซ้อนกัน (MultiIndex) ใช้ .agg() แบบตั้งชื่อเองแทนถ้าต้องการความชัดเจน

คำถามสัมภาษณ์

เมื่อไหร่ควรใช้ pivot_table แทน groupby

ใช้ pivot_table เมื่อต้องการนำเสนอผลลัพธ์เป็นตาราง "กว้าง" ที่มี 2 มิติ (แถว×คอลัมน์) พร้อมกัน เช่น รายงานสรุปที่จะส่งให้คนอื่นอ่านหรือทำเป็น dashboard ในขณะที่ groupby เหมาะกับตอนจะเอาผล ไปประมวลผลต่อในโค้ด (ผลลัพธ์เป็นรูปแบบยาว จัดการต่อง่ายกว่า)