การแปลงและกรองด้วย GroupBy
ใช้ transform() เพื่อเพิ่มสถิติระดับกลุ่มกลับมาเป็นคอลัมน์ และใช้ filter() เพื่อเก็บเฉพาะกลุ่มที่ตรงตามเงื่อนไข
การแปลงและกรองด้วย GroupBy เป็นบทเรียน Pandas & NumPy Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Pandas & NumPy Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน
ก้าวข้ามการรวมค่า
หลังจากเชี่ยวชาญ agg() แล้ว คำถามถัดไปที่เกิดขึ้นตามธรรมชาติคือ หากคุณต้องการเก็บแถวเดิมทั้งหมดไว้พร้อมเพิ่มสถิติระดับกลุ่มเข้าไป หรือเก็บไว้เฉพาะกลุ่มที่ตรงตามเงื่อนไข จะทำอย่างไร นี่คือจุดที่ transform() และ filter() เข้ามามีบทบาท เมธอดทั้งสองช่วยขยายการใช้งาน GroupBy จากการสรุปค่าอย่างง่าย ไปสู่การสร้างคุณลักษณะและการเลือกข้อมูล
ทำความเข้าใจ transform()
transform() ใช้ฟังก์ชันกับแต่ละกลุ่มและคืนผลลัพธ์ที่มีรูปร่างเหมือนกับ DataFrame เดิม — มีหนึ่งค่าต่อหนึ่งแถวเดิม ผลลัพธ์ของกลุ่มจะถูกกระจายกลับไปยังแต่ละแถวที่อยู่ในกลุ่มนั้น จึงเหมาะอย่างยิ่งสำหรับการเพิ่มสถิติระดับกลุ่มเป็นคอลัมน์ใหม่โดยไม่เปลี่ยนจำนวนแถว
import pandas as pd
df = pd.DataFrame({
'dept': ['Eng', 'HR', 'Eng', 'HR', 'Eng'],
'salary': [90000, 60000, 95000, 62000, 88000]
})
# Add a column with each employee's department average salary
df['dept_avg'] = df.groupby('dept')['salary'].transform('mean')
print(df)
# dept salary dept_avg
# 0 Eng 90000 91000.000
# 1 HR 60000 61000.000
# 2 Eng 95000 91000.000
# 3 HR 62000 61000.000
# 4 Eng 88000 91000.000กรณีการใช้งาน transform() ที่พบบ่อย
การใช้งาน transform() ที่พบบ่อย ได้แก่ การเพิ่มค่าเฉลี่ยของกลุ่มเพื่อปรับค่าข้อมูลให้เป็นมาตรฐาน การเพิ่มผลรวมของกลุ่มเพื่อคำนวณสัดส่วนของแต่ละแถวเมื่อเทียบกับยอดรวม และการเพิ่มอันดับภายในกลุ่มเพื่อดูว่าสมาชิกแต่ละรายอยู่ในระดับใดเมื่อเทียบกับสมาชิกอื่นในกลุ่ม ทั้งหมดนี้จะคงรูปร่างและดัชนีเดิมไว้ ทำให้สามารถใช้ผลลัพธ์ร่วมกับคอลัมน์เดิมได้ทันที
# Percentage of each employee's salary within their department total
df['pct_of_dept'] = (
df['salary'] / df.groupby('dept')['salary'].transform('sum') * 100
).round(1)
print(df[['dept', 'salary', 'pct_of_dept']])
# dept salary pct_of_dept
# Eng 90000 33.1
# HR 60000 49.2
# Eng 95000 34.9การใช้ฟังก์ชันแบบกำหนดเองใน transform()
เช่นเดียวกับ agg() ตรงที่ transform() รับฟังก์ชันที่เรียกใช้งานได้ทุกชนิด นอกเหนือจากชื่อที่เป็นสตริง ฟังก์ชันจะได้รับ Series ของค่าสำหรับกลุ่มหนึ่งกลุ่ม และต้องคืน Series ที่มีความยาวเท่ากัน หรือคืนค่าเดี่ยว (ซึ่งจะถูกกระจายไปยังทุกแถว) การคืนค่าเดี่ยวเป็นกรณีการใช้งานที่พบบ่อยที่สุด หากคืน Series ที่มีความยาวต่างกัน จะเกิดข้อผิดพลาด
# Z-score normalisation within each department
def zscore(s):
return (s - s.mean()) / s.std()
df['salary_zscore'] = df.groupby('dept')['salary'].transform(zscore)
print(df[['dept', 'salary', 'salary_zscore']].round(2))
# dept salary salary_zscore
# Eng 90000 -0.51
# HR 60000 -0.71
# Eng 95000 1.03เปรียบเทียบ agg() กับ transform()
ความแตกต่างสำคัญคือ agg() ลดจำนวนแถวลง (เหลือหนึ่งแถวต่อกลุ่ม) ขณะที่ transform() คงจำนวนแถวไว้ (หนึ่งแถวต่อแถวเดิม) ใช้ agg() เพื่อสร้างตารางสรุป และใช้ transform() เพื่อเพิ่มข้อมูลระดับกลุ่มเป็นคอลัมน์คุณลักษณะใหม่ใน DataFrame เดิม
g = df.groupby('dept')['salary']
# agg: 2 rows (one per unique dept)
print(g.agg('mean'))
# dept
# Eng 91000.0
# HR 61000.0
# transform: 5 rows (one per original row)
print(g.transform('mean'))
# 0 91000.0
# 1 61000.0
# 2 91000.0
# 3 61000.0
# 4 91000.0ทำความเข้าใจ filter()
filter() จะเก็บหรือละทิ้งทั้งกลุ่มโดยอิงจากฟังก์ชันบูลีน คุณส่งฟังก์ชันที่รับ DataFrame ย่อยของกลุ่มหนึ่งกลุ่ม และคืนค่า True (เก็บกลุ่มไว้) หรือ False (ลบกลุ่มออก) ผลลัพธ์คือส่วนย่อยของ DataFrame เดิม ซึ่งมีเฉพาะแถวจากกลุ่มที่ผ่านการทดสอบ
df2 = pd.DataFrame({
'dept': ['Eng', 'HR', 'Eng', 'HR', 'Eng', 'Legal'],
'salary': [90000, 60000, 95000, 62000, 88000, 70000]
})
# Keep only departments with at least 2 employees
big_depts = df2.groupby('dept').filter(lambda g: len(g) >= 2)
print(big_depts)
# dept, salary rows: Eng(3) and HR(2) remain; Legal(1) droppedกรองตามค่าการรวมของกลุ่ม
การใช้งาน filter() ที่พบบ่อยมากคือการเก็บกลุ่มที่ค่าการรวมผ่านเกณฑ์ที่กำหนด ตัวอย่างเช่น เก็บเฉพาะแผนกที่มีเงินเดือนเฉลี่ยสูงกว่าเป้าหมาย หรือเก็บเฉพาะหมวดหมู่สินค้าที่มียอดขายรวมสูงกว่าค่าขั้นต่ำ วิธีนี้ช่วยลบกลุ่มที่มีปริมาณน้อยออกก่อนการวิเคราะห์ขั้นต่อไป
# Keep only departments where average salary > 80000
high_paying = df2.groupby('dept').filter(
lambda g: g['salary'].mean() > 80000
)
print(high_paying)
# dept salary
# 0 Eng 90000
# 2 Eng 95000
# 4 Eng 88000
# (HR avg is 61000, filtered out)การใช้ transform() และ filter() ร่วมกัน
คุณสามารถใช้ transform() และ filter() ตามลำดับ เพื่อเพิ่มข้อมูลให้สมบูรณ์แล้วจึงจำกัดข้อมูลให้แคบลง ขั้นแรกใช้ filter() เพื่อลบกลุ่มที่ไม่เกี่ยวข้อง จากนั้นใช้ transform() กับผลลัพธ์ที่กรองแล้วเพื่อเพิ่มคุณลักษณะระดับกลุ่ม การผสมผสานนี้ทำให้ได้ชุดข้อมูลย่อยที่สะอาดและมีคุณลักษณะครบถ้วน พร้อมสำหรับการสร้างแบบจำลองหรือการจัดทำรายงาน
# Step 1: keep only large departments
filtered = df2.groupby('dept').filter(lambda g: len(g) >= 2)
# Step 2: add group mean salary to the filtered result
filtered = filtered.copy()
filtered['dept_avg'] = filtered.groupby('dept')['salary'].transform('mean')
print(filtered)ใช้ transform() เติมค่าล่วงหน้าภายในกลุ่ม
transform() ยังมีประโยชน์กับฟังก์ชันที่ไม่ใช่ตัวเลขด้วย รูปแบบที่นิยมคือการเติมค่าที่หายไปภายในกลุ่ม โดยใช้การเติมค่าล่วงหน้าหรือค่ามัธยฐานของกลุ่ม ซึ่งดีกว่าการเติมค่าทั้งหมดด้วยค่าเดียวเป็นอย่างมาก ส่งฟังก์ชันแลมบ์ดาที่เรียก fillna() กับ Series ของกลุ่ม แล้วผลลัพธ์จะมีดัชนีเดียวกับ DataFrame เดิม
import numpy as np
df3 = pd.DataFrame({
'dept': ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
'salary': [90000, np.nan, 60000, np.nan, 88000]
})
# Fill NaN with the group mean
df3['salary_filled'] = df3.groupby('dept')['salary'].transform(
lambda s: s.fillna(s.mean())
)
print(df3)รูปแบบเชิงปฏิบัติ: ตำแหน่งสัมพัทธ์
กรณีการใช้งานทางธุรกิจที่มีประโยชน์อย่างหนึ่งคือการคำนวณตำแหน่งของแต่ละแถวเมื่อเทียบกับกลุ่มของตนเอง ด้วยการใช้ transform() ร่วมกับการคำนวณทางคณิตศาสตร์ คุณสามารถเพิ่มคอลัมน์ เช่น เงินเดือนลบด้วยค่าเฉลี่ยของกลุ่ม (ค่าความเบี่ยงเบน) เงินเดือนในรูปเศษส่วนของยอดรวมกลุ่ม หรือค่าสถานะบูลีนที่ระบุว่าพนักงานรายนี้มีรายได้สูงกว่าค่ามัธยฐานของกลุ่มหรือไม่ คุณลักษณะเหล่านี้มีประโยชน์อย่างมากสำหรับแดชบอร์ดและแบบจำลองการเรียนรู้ของเครื่อง
df['dept_total'] = df.groupby('dept')['salary'].transform('sum')
df['pct_of_total'] = (df['salary'] / df['dept_total'] * 100).round(1)
df['above_avg'] = df['salary'] > df.groupby('dept')['salary'].transform('mean')
print(df[['dept', 'salary', 'pct_of_total', 'above_avg']])ข้อควรพิจารณาด้านประสิทธิภาพ
ทั้ง transform() และ filter() ที่ใช้ฟังก์ชันในตัวแบบสตริงทำงานได้รวดเร็ว เพราะใช้เส้นทางการทำงานของโค้ดที่ได้รับการปรับให้เหมาะสม อย่างไรก็ตาม เมื่อคุณส่งฟังก์ชันแลมบ์ดาหรือฟังก์ชัน Python แบบกำหนดเอง Pandas ต้องเรียกฟังก์ชันนั้นหนึ่งครั้งต่อหนึ่งกลุ่ม ซึ่งอาจช้าเมื่อข้อมูลมีกลุ่มจำนวนมาก หากต้องการประสิทธิภาพสูงสุดกับชุดข้อมูลขนาดใหญ่ ให้ตรวจสอบว่าตรรกะแบบกำหนดเองของคุณสามารถเขียนด้วยฟังก์ชันในตัวแบบสตริงแทนได้หรือไม่
# Slower: custom lambda (called once per group)
df['dept_mean_slow'] = df.groupby('dept')['salary'].transform(lambda s: s.mean())
# Faster: built-in string shortcut (vectorised C path)
df['dept_mean_fast'] = df.groupby('dept')['salary'].transform('mean')
# Both give identical results, but the built-in is significantly fasterตรวจสอบความเข้าใจ
ทดสอบความเข้าใจเกี่ยวกับ GroupBy transform() และ filter() จากบทเรียนนี้
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า transform() คืนค่าสถิติของกลุ่มที่ถูกกระจายกลับไปจนมีจำนวนแถวเท่ากับแถวเดิม จึงเหมาะสำหรับการเพิ่มคุณลักษณะระดับกลุ่ม filter() เก็บหรือลบทั้งกลุ่มโดยอิงตามเงื่อนไขบูลีน และการใช้ทั้งสองเมธอดร่วมกันช่วยให้คุณสร้างชุดข้อมูลที่มีคุณลักษณะครบถ้วนและผ่านการกรองแล้วสำหรับการวิเคราะห์ในขั้นต่อไป บทถัดไปเราจะสำรวจวิธีรวม DataFrame ด้วย pd.concat
เรียนรู้ Python ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “การแปลงและกรองด้วย GroupBy” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแปลงและกรองด้วย GroupBy” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Pandas & NumPy Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การแปลงและกรองด้วย GroupBy”
ใช้ transform() เพื่อเพิ่มสถิติระดับกลุ่มกลับมาเป็นคอลัมน์ และใช้ filter() เพื่อเก็บเฉพาะกลุ่มที่ตรงตามเงื่อนไข คุณปฏิบัติ Pandas & NumPy Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Pandas & NumPy Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Pandas & NumPy Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การแปลงและกรองด้วย GroupBy” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Pandas & NumPy Academy นี้ได้ไหม
ได้ บทเรียน Pandas & NumPy Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- รูปแบบแยก-ประมวลผล-รวม
- GroupBy ด้วยคีย์เดียวและหลายคีย์
- เมธอด agg()
- การแปลงและกรองด้วย GroupBy