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 จะเอาทุกคอลัมน์ไปแปลงเป็นแถวหมด ไม่เหลือคอลัมน์บอกที่มาของแต่ละแถวเลย
ตัวอย่างแก้โจทย์
กด "ขั้นต่อไป" ทีละขั้น ลองรันและแก้โค้ดในแต่ละขั้นได้
จำนวนออเดอร์แต่ละคู่ (สถานะ, วิธีจ่ายเงิน) แบบตารางกว้าง
อยากเห็นจำนวนออเดอร์แยกตามสถานะและวิธีจ่ายเงินพร้อมกันในตารางเดียว
pivot_tableจัดวางค่าหนึ่งคอลัมน์เป็นindex(แถว) อีกคอลัมน์เป็นcolumns(คอลัมน์) ถ้าบางคู่ไม่มีข้อมูลเลย ช่องนั้นจะเป็นค่าว่าง
แปลงคอลัมน์ price/cost ให้เป็นแถว (long format) ด้วย melt
บางครั้งอยากได้ข้อมูลแบบ "ยาว" (แต่ละแถวคือ 1 ค่า) แทนที่จะเป็น "กว้าง" (แต่ละคอลัมน์คือ 1 ตัวชี้วัด)
ดูตารางแบบกว้างก่อน (product_id, price, cost อยู่คนละคอลัมน์)
เติมช่องว่าง
แทน ___ ด้วยโค้ดที่ถูกต้อง แล้วกดตรวจคำตอบ
ราคาเฉลี่ยของสินค้าแต่ละหมวด (ปัดเป็นจำนวนเต็ม) แบบ 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
สรุป
- pivot_table สร้างตารางสรุปแบบกว้าง (index=แถว, columns=คอลัมน์, values=ค่า, aggfunc=วิธีสรุป)
- melt แปลงข้อมูลจากกว้างเป็นยาว เป็นการย้อนกลับของ pivot_table
- aggfunc เป็น list ทำให้ได้คอลัมน์ซ้อนกัน (MultiIndex) ใช้ .agg() แบบตั้งชื่อเองแทนถ้าต้องการความชัดเจน
คำถามสัมภาษณ์
เมื่อไหร่ควรใช้ pivot_table แทน groupby
ใช้ pivot_table เมื่อต้องการนำเสนอผลลัพธ์เป็นตาราง "กว้าง" ที่มี 2 มิติ (แถว×คอลัมน์) พร้อมกัน
เช่น รายงานสรุปที่จะส่งให้คนอื่นอ่านหรือทำเป็น dashboard ในขณะที่ groupby เหมาะกับตอนจะเอาผล
ไปประมวลผลต่อในโค้ด (ผลลัพธ์เป็นรูปแบบยาว จัดการต่อง่ายกว่า)