การวิเคราะห์ข้อมูลในโลกจริงมักต้องการการสรุปผลและจัดกลุ่มข้อมูลเพื่อหาข้อมูลเชิงลึก (Insights) ซึ่งเปรียบเสมือนการใช้ Pivot Table ใน Excel หรือคำสั่ง GROUP BY ใน SQL แต่ด้วยความยืดหยุ่นและประสิทธิภาพที่สูงกว่า Pandas มีเครื่องมือที่ทรงพลังสำหรับการทำงานนี้
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#fbf1c7','primaryTextColor':'#3c3836','primaryBorderColor':'#458588','lineColor':'#98971a','secondaryColor':'#d79921','tertiaryColor':'#cc241d','background':'#282828','mainBkg':'#fbf1c7','secondaryBkg':'#ebdbb2','textColor':'#3c3836','fontSize':'16px'}}}%%
graph LR
A[ข้อมูลดิบ
Raw Data] --> B[จัดกลุ่ม
GroupBy]
B --> C[รวบรวม
Aggregate]
C --> D[ผลลัพธ์
Results]
style A fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
style B fill:#fe8019,stroke:#3c3836,stroke-width:2px,color:#282828
style C fill:#d3869b,stroke:#3c3836,stroke-width:2px,color:#282828
style D fill:#83a598,stroke:#3c3836,stroke-width:2px,color:#282828
การจัดกลุ่มข้อมูลเป็นกระบวนการที่แบ่งข้อมูลออกเป็นกลุ่มตามคุณสมบัติที่กำหนด แล้วทำการคำนวณในแต่ละกลุ่ม
GroupBy ใน Pandas ทำงานตามหลักการ Split-Apply-Combine:
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#fbf1c7','primaryTextColor':'#3c3836','primaryBorderColor':'#458588','lineColor':'#98971a','secondaryColor':'#d79921','tertiaryColor':'#cc241d','background':'#282828','mainBkg':'#fbf1c7','secondaryBkg':'#ebdbb2','textColor':'#3c3836','fontSize':'16px'}}}%%
flowchart TB
subgraph Split["1. Split - แบ่งกลุ่ม"]
A[DataFrame เดิม] --> B1[กลุ่ม A]
A --> B2[กลุ่ม B]
A --> B3[กลุ่ม C]
end
subgraph Apply["2. Apply - ประมวลผล"]
B1 --> C1[คำนวณ sum/mean/count]
B2 --> C2[คำนวณ sum/mean/count]
B3 --> C3[คำนวณ sum/mean/count]
end
subgraph Combine["3. Combine - รวมผล"]
C1 --> D[DataFrame ใหม่]
C2 --> D
C3 --> D
end
style A fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
style B1 fill:#fe8019,stroke:#3c3836,stroke-width:2px,color:#282828
style B2 fill:#fe8019,stroke:#3c3836,stroke-width:2px,color:#282828
style B3 fill:#fe8019,stroke:#3c3836,stroke-width:2px,color:#282828
style C1 fill:#d3869b,stroke:#3c3836,stroke-width:2px,color:#282828
style C2 fill:#d3869b,stroke:#3c3836,stroke-width:2px,color:#282828
style C3 fill:#d3869b,stroke:#3c3836,stroke-width:2px,color:#282828
style D fill:#83a598,stroke:#3c3836,stroke-width:2px,color:#282828
import pandas as pd
import numpy as np
def create_sales_data():
"""
สร้างข้อมูลตัวอย่างยอดขาย
Returns:
DataFrame: ข้อมูลยอดขายพนักงานแบ่งตามภูมิภาคและผลิตภัณฑ์
"""
data = {
'พนักงาน': ['สมชาย', 'สมหญิง', 'วิชัย', 'อรุณ', 'สมชาย',
'สมหญิง', 'วิชัย', 'อรุณ', 'สมชาย', 'สมหญิง'],
'ภูมิภาค': ['เหนือ', 'เหนือ', 'กลาง', 'กลาง', 'เหนือ',
'เหนือ', 'กลาง', 'กลาง', 'ใต้', 'ใต้'],
'ผลิตภัณฑ์': ['A', 'B', 'A', 'B', 'C',
'A', 'B', 'C', 'A', 'B'],
'ยอดขาย': [100, 150, 200, 120, 180,
160, 140, 190, 110, 170],
'จำนวน': [5, 8, 10, 6, 9,
8, 7, 10, 6, 9]
}
return pd.DataFrame(data)
# สร้างข้อมูลตัวอย่าง
df = create_sales_data()
print("ข้อมูลดิบ (Raw Data):")
print(df)
print("\n" + "="*60 + "\n")
# ตัวอย่างที่ 1: จัดกลุ่มตามภูมิภาคและหายอดขายรวม
grouped_region = df.groupby('ภูมิภาค')['ยอดขาย'].sum()
print("ยอดขายรวมแต่ละภูมิภาค:")
print(grouped_region)
print("\n" + "="*60 + "\n")
# ตัวอย่างที่ 2: จัดกลุ่มหลาย Column
grouped_multi = df.groupby(['ภูมิภาค', 'ผลิตภัณฑ์'])['ยอดขาย'].sum()
print("ยอดขายแยกตามภูมิภาคและผลิตภัณฑ์:")
print(grouped_multi)
ผลลัพธ์:
ข้อมูลดิบ (Raw Data):
พนักงาน ภูมิภาค ผลิตภัณฑ์ ยอดขาย จำนวน
0 สมชาย เหนือ A 100 5
1 สมหญิง เหนือ B 150 8
...
ยอดขายรวมแต่ละภูมิภาค:
ภูมิภาค
กลาง 650
ใต้ 280
เหนือ 590
Name: ยอดขาย, dtype: int64
เมื่อใช้ .groupby() จะได้ GroupBy Object ซึ่งยังไม่ได้คำนวณจริง (Lazy Evaluation) จนกว่าจะเรียกใช้ฟังก์ชันรวบรวม
def explore_groupby_object():
"""
สำรวจคุณสมบัติของ GroupBy Object
"""
df = create_sales_data()
# สร้าง GroupBy Object
grouped = df.groupby('ภูมิภาค')
# 1. ดูจำนวนกลุ่ม
print(f"จำนวนกลุ่มทั้งหมด: {grouped.ngroups}")
# 2. ดูชื่อกลุ่มและขนาดของแต่ละกลุ่ม
print("\nขนาดแต่ละกลุ่ม:")
print(grouped.size())
# 3. เข้าถึงกลุ่มเดียว
print("\nข้อมูลในกลุ่ม 'เหนือ':")
print(grouped.get_group('เหนือ'))
# 4. วนลูปผ่านแต่ละกลุ่ม
print("\nวนลูปแต่ละกลุ่ม:")
for name, group in grouped:
print(f"\n{name}:")
print(group.head(2))
# เรียกใช้ฟังก์ชัน
explore_groupby_object()
การจัดกลุ่มด้วยฟังก์ชัน:
def groupby_with_function():
"""
ตัวอย่างการใช้ฟังก์ชันในการจัดกลุ่ม
"""
df = create_sales_data()
# จัดกลุ่มตามความยาวของชื่อพนักงาน
def name_length_category(name):
"""แบ่งกลุ่มตามความยาวชื่อ"""
if len(name) <= 5:
return 'สั้น'
else:
return 'ยาว'
# ใช้ฟังก์ชันกับ Column
grouped = df.groupby(df['พนักงาน'].apply(name_length_category))['ยอดขาย'].sum()
print("ยอดขายแบ่งตามความยาวชื่อ:")
print(grouped)
groupby_with_function()
หลังจากจัดกลุ่มข้อมูลแล้ว ขั้นตอนต่อไปคือการคำนวณค่าสถิติต่างๆ ภายในแต่ละกลุ่ม
Pandas มีฟังก์ชันรวบรวมที่ใช้งานบ่อย:
| ฟังก์ชัน | ความหมาย | ตัวอย่างการใช้ |
|---|---|---|
.sum() |
ผลรวม | grouped.sum() |
.mean() |
ค่าเฉลี่ย | grouped.mean() |
.median() |
มัธยฐาน | grouped.median() |
.min() |
ค่าต่ำสุด | grouped.min() |
.max() |
ค่าสูงสุด | grouped.max() |
.count() |
นับจำนวน | grouped.count() |
.std() |
ส่วนเบี่ยงเบนมาตรฐาน | grouped.std() |
.var() |
ความแปรปรวน | grouped.var() |
def basic_aggregations():
"""
ตัวอย่างการใช้ฟังก์ชันรวบรวมพื้นฐาน
"""
df = create_sales_data()
grouped = df.groupby('ภูมิภาค')['ยอดขาย']
print("=== สถิติพื้นฐานแต่ละภูมิภาค ===\n")
# ผลรวม
print("1. ยอดขายรวม (Sum):")
print(grouped.sum())
print()
# ค่าเฉลี่ย
print("2. ยอดขายเฉลี่ย (Mean):")
print(grouped.mean().round(2))
print()
# นับจำนวน
print("3. จำนวนรายการ (Count):")
print(grouped.count())
print()
# ค่าสูงสุดและต่ำสุด
print("4. ยอดขายสูงสุด-ต่ำสุด:")
print(pd.DataFrame({
'สูงสุด': grouped.max(),
'ต่ำสุด': grouped.min()
}))
basic_aggregations()
ค่าเฉลี่ย (Mean):
โดยที่:
ส่วนเบี่ยงเบนมาตรฐาน (Standard Deviation):
โดยที่:
def multiple_aggregations():
"""
ใช้ฟังก์ชันรวบรวมหลายตัวพร้อมกัน
"""
df = create_sales_data()
# วิธีที่ 1: ใช้ .agg() กับ list ของฟังก์ชัน
result1 = df.groupby('ภูมิภาค')['ยอดขาย'].agg(['sum', 'mean', 'count', 'std'])
result1.columns = ['ผลรวม', 'ค่าเฉลี่ย', 'จำนวน', 'ส่วนเบี่ยงเบน']
print("=== สถิติแบบรวม ===")
print(result1.round(2))
print()
# วิธีที่ 2: คำนวณแยก Column
result2 = df.groupby('ภูมิภาค').agg({
'ยอดขาย': ['sum', 'mean'],
'จำนวน': ['sum', 'mean']
})
print("=== สถิติแยกตาม Column ===")
print(result2.round(2))
multiple_aggregations()
def custom_aggregation():
"""
สร้างฟังก์ชันรวบรวมแบบกำหนดเอง
"""
df = create_sales_data()
# ฟังก์ชัน custom: หาช่วงห่าง (range)
def value_range(x):
"""คำนวณช่วงห่างระหว่างค่าสูงสุดและต่ำสุด"""
return x.max() - x.min()
# ฟังก์ชัน custom: หา coefficient of variation
def coef_variation(x):
"""คำนวณค่า CV (ส่วนเบี่ยงเบน / ค่าเฉลี่ย * 100)"""
return (x.std() / x.mean()) * 100 if x.mean() != 0 else 0
result = df.groupby('ภูมิภาค')['ยอดขาย'].agg([
('ค่าเฉลี่ย', 'mean'),
('ช่วงห่าง', value_range),
('CV%', coef_variation)
])
print("=== สถิติแบบ Custom ===")
print(result.round(2))
custom_aggregation()
.agg() (หรือ .aggregate()) เป็นเครื่องมือที่ทรงพลังสำหรับการคำนวณหลายค่าพร้อมกัน โดยสามารถระบุฟังก์ชันต่างกันสำหรับแต่ละ Column
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#fbf1c7','primaryTextColor':'#3c3836','primaryBorderColor':'#458588','lineColor':'#98971a','secondaryColor':'#d79921','tertiaryColor':'#cc241d','background':'#282828','mainBkg':'#fbf1c7','secondaryBkg':'#ebdbb2','textColor':'#3c3836','fontSize':'14px'}}}%%
graph TB
A[.agg Methods
วิธีใช้ .agg] --> B[String Names
ชื่อฟังก์ชัน]
A --> C[Function Objects
ตัวฟังก์ชัน]
A --> D[Lambda
ฟังก์ชัน Lambda]
A --> E[Dictionary
แบบ Dict]
A --> F[List of Tuples
แบบ Tuple]
B --> B1["'sum', 'mean'"]
C --> C1["np.sum, np.mean"]
D --> D1["lambda x: x.max()"]
E --> E1["{'col1': 'sum',
'col2': 'mean'}"]
F --> F1["[('total', 'sum'),
('avg', 'mean')]"]
style A fill:#fe8019,stroke:#3c3836,stroke-width:3px,color:#282828
style B fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
style C fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
style D fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
style E fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
style F fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
def agg_various_methods():
"""
ตัวอย่างการใช้ .agg() แบบต่างๆ
"""
df = create_sales_data()
grouped = df.groupby('ภูมิภาค')
# วิธีที่ 1: ใช้ string ของชื่อฟังก์ชัน
print("1. ใช้ชื่อฟังก์ชันแบบ string:")
result1 = grouped['ยอดขาย'].agg(['sum', 'mean', 'max'])
print(result1)
print("\n" + "="*60 + "\n")
# วิธีที่ 2: ใช้ dictionary กำหนดแยกตาม Column
print("2. ใช้ dictionary กำหนดฟังก์ชันแยก Column:")
result2 = grouped.agg({
'ยอดขาย': ['sum', 'mean'],
'จำนวน': ['sum', 'max'],
'พนักงาน': 'count' # นับจำนวนรายการ
})
print(result2)
print("\n" + "="*60 + "\n")
# วิธีที่ 3: ใช้ tuple เพื่อตั้งชื่อ Column ใหม่
print("3. ใช้ tuple ตั้งชื่อ Column:")
result3 = grouped['ยอดขาย'].agg([
('ยอดรวม', 'sum'),
('ยอดเฉลี่ย', 'mean'),
('ยอดสูงสุด', 'max')
])
print(result3)
print("\n" + "="*60 + "\n")
# วิธีที่ 4: ผสม built-in และ custom functions
print("4. ผสมฟังก์ชัน built-in และ custom:")
result4 = grouped['ยอดขาย'].agg([
'sum',
'mean',
('range', lambda x: x.max() - x.min()),
('top_3_avg', lambda x: x.nlargest(3).mean())
])
print(result4.round(2))
agg_various_methods()
def agg_with_numpy():
"""
ใช้ฟังก์ชันจาก NumPy ใน .agg()
"""
df = create_sales_data()
grouped = df.groupby('ภูมิภาค')['ยอดขาย']
# ใช้ฟังก์ชันจาก NumPy
result = grouped.agg([
('Mean', np.mean),
('Median', np.median),
('Std', np.std),
('Q1', lambda x: np.percentile(x, 25)),
('Q3', lambda x: np.percentile(x, 75))
])
print("=== สถิติเชิงลึกด้วย NumPy ===")
print(result.round(2))
# คำนวณ IQR (Interquartile Range)
result['IQR'] = result['Q3'] - result['Q1']
print("\nพร้อม IQR:")
print(result.round(2))
agg_with_numpy()
Named Aggregation ช่วยให้เขียน code ที่อ่านง่ายขึ้น โดยใช้ pd.NamedAgg:
def named_aggregation():
"""
ใช้ Named Aggregation เพื่อความชัดเจน
"""
df = create_sales_data()
result = df.groupby('ภูมิภาค').agg(
ยอดขายรวม=pd.NamedAgg(column='ยอดขาย', aggfunc='sum'),
ยอดขายเฉลี่ย=pd.NamedAgg(column='ยอดขาย', aggfunc='mean'),
จำนวนสินค้ารวม=pd.NamedAgg(column='จำนวน', aggfunc='sum'),
จำนวนรายการ=pd.NamedAgg(column='พนักงาน', aggfunc='count')
)
print("=== Named Aggregation ===")
print(result.round(2))
# คำนวณ metric เพิ่มเติม
result['ยอดเฉลี่ยต่อสินค้า'] = result['ยอดขายรวม'] / result['จำนวนสินค้ารวม']
print("\nพร้อมการคำนวณเพิ่มเติม:")
print(result.round(2))
named_aggregation()
ความแตกต่างสำคัญ:
| คุณสมบัติ | .agg() |
.transform() |
|---|---|---|
| Output Shape | รวมกลุ่ม (ลดขนาด) | ขนาดเท่าเดิม |
| Use Case | สรุปผลแต่ละกลุ่ม | เติมค่ากลับในข้อมูลเดิม |
| ตัวอย่าง | หายอดขายรวมแต่ละภูมิภาค | เติมค่าเฉลี่ยภูมิภาคในทุก row |
def agg_vs_transform():
"""
เปรียบเทียบ .agg() และ .transform()
"""
df = create_sales_data()
# ใช้ .agg() - ลดขนาดเหลือแค่กลุ่ม
agg_result = df.groupby('ภูมิภาค')['ยอดขาย'].agg(['mean', 'sum'])
print("=== ผลลัพธ์จาก .agg() ===")
print(agg_result)
print(f"Shape: {agg_result.shape}")
print("\n" + "="*60 + "\n")
# ใช้ .transform() - ขนาดเท่าเดิม
df['ยอดเฉลี่ยภูมิภาค'] = df.groupby('ภูมิภาค')['ยอดขาย'].transform('mean')
df['ส่วนต่างจากเฉลี่ย'] = df['ยอดขาย'] - df['ยอดเฉลี่ยภูมิภาค']
print("=== ผลลัพธ์จาก .transform() ===")
print(df[['พนักงาน', 'ภูมิภาค', 'ยอดขาย', 'ยอดเฉลี่ยภูมิภาค', 'ส่วนต่างจากเฉลี่ย']])
print(f"Shape: {df.shape}")
agg_vs_transform()
การใช้ .transform() กับ Lambda:
โดยที่:
def standardize_by_group():
"""
ทำ Standardization (Z-score) ภายในแต่ละกลุ่ม
"""
df = create_sales_data()
# คำนวณ Z-score สำหรับแต่ละภูมิภาค
df['z_score'] = df.groupby('ภูมิภาค')['ยอดขาย'].transform(
lambda x: (x - x.mean()) / x.std()
)
print("=== Z-score ภายในแต่ละภูมิภาค ===")
print(df[['พนักงาน', 'ภูมิภาค', 'ยอดขาย', 'z_score']].round(3))
standardize_by_group()
Pivot Table เป็นเครื่องมือสำคัญในการสรุปและจัดกลุ่มข้อมูลแบบ 2 มิติ เหมาะสำหรับการวิเคราะห์เชิงลึกและสร้างรายงาน
def create_pivot_table_basic():
"""
สร้าง Pivot Table พื้นฐาน
"""
# สร้างข้อมูลตัวอย่างที่ซับซ้อนขึ้น
data = {
'วันที่': pd.date_range('2024-01-01', periods=20, freq='D'),
'ภูมิภาค': ['เหนือ', 'กลาง', 'ใต้', 'อีสาน'] * 5,
'ผลิตภัณฑ์': ['A', 'B', 'C', 'A', 'B'] * 4,
'ยอดขาย': np.random.randint(100, 500, 20),
'กำไร': np.random.randint(20, 100, 20)
}
df = pd.DataFrame(data)
# Pivot Table พื้นฐาน
pivot1 = pd.pivot_table(
df,
values='ยอดขาย', # Column ที่ต้องการสรุป
index='ภูมิภาค', # แถว
columns='ผลิตภัณฑ์', # คอลัมน์
aggfunc='sum', # ฟังก์ชันรวบรวม
fill_value=0 # แทนที่ NaN ด้วย 0
)
print("=== Pivot Table: ยอดขายแต่ละภูมิภาคตามผลิตภัณฑ์ ===")
print(pivot1)
print("\n" + "="*60 + "\n")
# เพิ่ม margins (รวมทั้งหมด)
pivot2 = pd.pivot_table(
df,
values='ยอดขาย',
index='ภูมิภาค',
columns='ผลิตภัณฑ์',
aggfunc='sum',
fill_value=0,
margins=True, # เพิ่มแถว/คอลัมน์รวม
margins_name='รวม'
)
print("=== Pivot Table พร้อม Margins ===")
print(pivot2)
create_pivot_table_basic()
def pivot_table_multiple_agg():
"""
Pivot Table ที่ใช้หลายฟังก์ชันพร้อมกัน
"""
data = {
'ภูมิภาค': ['เหนือ', 'กลาง', 'ใต้', 'อีสาน'] * 5,
'ผลิตภัณฑ์': ['A', 'B', 'C'] * 6 + ['A', 'B'],
'ยอดขาย': np.random.randint(100, 500, 20),
'จำนวน': np.random.randint(5, 20, 20)
}
df = pd.DataFrame(data)
# Pivot Table หลายค่า
pivot = pd.pivot_table(
df,
values=['ยอดขาย', 'จำนวน'], # หลาย values
index='ภูมิภาค',
columns='ผลิตภัณฑ์',
aggfunc={
'ยอดขาย': ['sum', 'mean'], # หลายฟังก์ชันต่อ column
'จำนวน': 'sum'
},
fill_value=0
)
print("=== Pivot Table หลายค่าและหลายฟังก์ชัน ===")
print(pivot.round(2))
pivot_table_multiple_agg()
Cross Tabulation ใช้สำหรับนับความถี่ระหว่าง 2 ตัวแปร:
def cross_tabulation_example():
"""
ตัวอย่างการใช้ pd.crosstab()
"""
# สร้างข้อมูลลูกค้า
data = {
'เพศ': ['ชาย', 'หญิง', 'ชาย', 'หญิง'] * 10,
'ช่วงอายุ': ['18-25', '26-35', '36-45', '46+'] * 10,
'ผลิตภัณฑ์ที่ซื้อ': np.random.choice(['A', 'B', 'C'], 40)
}
df = pd.DataFrame(data)
# Cross-tab พื้นฐาน: นับความถี่
crosstab1 = pd.crosstab(
df['เพศ'],
df['ช่วงอายุ'],
margins=True,
margins_name='รวม'
)
print("=== Cross Tabulation: จำนวนลูกค้าแต่ละกลุ่ม ===")
print(crosstab1)
print("\n" + "="*60 + "\n")
# Cross-tab แบบเปอร์เซ็นต์
crosstab2 = pd.crosstab(
df['เพศ'],
df['ช่วงอายุ'],
normalize='index' # normalize ตามแถว (0-1)
) * 100 # แปลงเป็น %
print("=== Cross Tabulation: เปอร์เซ็นต์ ===")
print(crosstab2.round(2))
print("\n" + "="*60 + "\n")
# Cross-tab 3 มิติ
crosstab3 = pd.crosstab(
[df['เพศ'], df['ช่วงอายุ']], # หลาย index
df['ผลิตภัณฑ์ที่ซื้อ']
)
print("=== Cross Tabulation: 3 มิติ ===")
print(crosstab3)
cross_tabulation_example()
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#fbf1c7','primaryTextColor':'#3c3836','primaryBorderColor':'#458588','lineColor':'#98971a','secondaryColor':'#d79921','tertiaryColor':'#cc241d','background':'#282828','mainBkg':'#fbf1c7','secondaryBkg':'#ebdbb2','textColor':'#3c3836','fontSize':'14px'}}}%%
graph TB
A{ต้องการอะไร?
What do you need?}
A -->|รูปแบบตาราง 2 มิติ
2D Table Format| B[Pivot Table]
A -->|การคำนวณที่ซับซ้อน
Complex Calculations| C[GroupBy + Agg]
A -->|นับความถี่
Frequency Count| D[Crosstab]
B --> B1[ใช้เมื่อ:
- ต้องการรูปแบบ matrix
- มี 2+ มิติในการวิเคราะห์
- ต้องการ fill_value]
C --> C1[ใช้เมื่อ:
- ต้องการควบคุมการคำนวณ
- ต้องการ transform
- การคำนวณหลายขั้นตอน]
D --> D1[ใช้เมื่อ:
- นับความถี่เท่านั้น
- ข้อมูล categorical
- ต้องการ normalize]
style A fill:#fe8019,stroke:#3c3836,stroke-width:3px,color:#282828
style B fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
style C fill:#83a598,stroke:#3c3836,stroke-width:2px,color:#282828
style D fill:#d3869b,stroke:#3c3836,stroke-width:2px,color:#282828
style B1 fill:#ebdbb2,stroke:#3c3836,stroke-width:1px,color:#282828
style C1 fill:#ebdbb2,stroke:#3c3836,stroke-width:1px,color:#282828
style D1 fill:#ebdbb2,stroke:#3c3836,stroke-width:1px,color:#282828
| เกณฑ์การเลือก | GroupBy + Agg | Pivot Table | Crosstab |
|---|---|---|---|
| รูปแบบผลลัพธ์ | Series/DataFrame | DataFrame (2D) | DataFrame (2D) |
| ความยืดหยุ่น | สูงมาก | ปานกลาง | น้อย |
| ความเหมาะสม | การคำนวณซับซ้อน | รายงานสรุป | นับความถี่ |
| Performance | เร็ว | ปานกลาง | เร็ว |
| การใช้งาน | ทุกประเภท | ข้อมูลที่ต้องการแกน 2 มิติ | Categorical data |
def comparison_groupby_pivot():
"""
เปรียบเทียบผลลัพธ์ระหว่าง GroupBy และ Pivot Table
"""
df = create_sales_data()
# วิธี GroupBy
print("=== ใช้ GroupBy ===")
groupby_result = df.groupby(['ภูมิภาค', 'ผลิตภัณฑ์'])['ยอดขาย'].sum()
print(groupby_result)
print("\n" + "="*60 + "\n")
# วิธี Pivot Table (ให้ผลลัพธ์เหมือนกัน แต่รูปแบบต่าง)
print("=== ใช้ Pivot Table ===")
pivot_result = pd.pivot_table(
df,
values='ยอดขาย',
index='ภูมิภาค',
columns='ผลิตภัณฑ์',
aggfunc='sum',
fill_value=0
)
print(pivot_result)
print("\n" + "="*60 + "\n")
# แปลง Pivot กลับเป็น Long Format (Unpivot)
print("=== Unpivot (melt) กลับ ===")
melted = pivot_result.reset_index().melt(
id_vars='ภูมิภาค',
var_name='ผลิตภัณฑ์',
value_name='ยอดขาย'
)
print(melted)
comparison_groupby_pivot()
def sales_report_example():
"""
ตัวอย่างการสร้างรายงานยอดขายแบบครบวงจร
"""
# สร้างข้อมูลยอดขายรายเดือน
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=365, freq='D')
data = {
'วันที่': np.random.choice(dates, 1000),
'ภูมิภาค': np.random.choice(['เหนือ', 'กลาง', 'ใต้', 'อีสาน'], 1000),
'ผลิตภัณฑ์': np.random.choice(['A', 'B', 'C', 'D'], 1000),
'ยอดขาย': np.random.randint(100, 1000, 1000),
'ต้นทุน': np.random.randint(50, 500, 1000)
}
df = pd.DataFrame(data)
df['กำไร'] = df['ยอดขาย'] - df['ต้นทุน']
df['เดือน'] = df['วันที่'].dt.to_period('M')
# รายงานที่ 1: สรุปรายเดือนแต่ละภูมิภาค
report1 = pd.pivot_table(
df,
values=['ยอดขาย', 'กำไร'],
index='เดือน',
columns='ภูมิภาค',
aggfunc='sum',
margins=True,
margins_name='รวมทั้งหมด'
)
print("=== รายงานยอดขายรายเดือนแต่ละภูมิภาค ===")
print(report1.head(10))
print("\n" + "="*60 + "\n")
# รายงานที่ 2: Top Products
report2 = df.groupby('ผลิตภัณฑ์').agg({
'ยอดขาย': ['sum', 'mean', 'count'],
'กำไร': 'sum'
}).round(2)
report2.columns = ['ยอดรวม', 'ยอดเฉลี่ย', 'จำนวนรายการ', 'กำไรรวม']
report2 = report2.sort_values('ยอดรวม', ascending=False)
report2['% กำไร'] = (report2['กำไรรวม'] / report2['ยอดรวม'] * 100).round(2)
print("=== รายงานผลิตภัณฑ์ขายดี ===")
print(report2)
sales_report_example()
การรวบรวมและจัดกลุ่มข้อมูลเป็นทักษะสำคัญที่สุดในการวิเคราะห์ข้อมูลด้วย Pandas สามารถสรุปประเด็นสำคัญได้ดังนี้:
.agg() สำหรับการคำนวณหลายค่า, .transform() สำหรับเติมค่ากลับ.agg() แบบ dictionary เมื่อต้องการฟังก์ชันต่างกันแต่ละ column.transform() เมื่อต้องการเติมค่าสถิติกลับไปในข้อมูลเดิม.reset_index() เพื่อแปลง MultiIndex เป็น columns ปกติ.unstack() หรือ .pivot() เพื่อ reshape ข้อมูล
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#fbf1c7','primaryTextColor':'#3c3836','primaryBorderColor':'#458588','lineColor':'#98971a','secondaryColor':'#d79921','tertiaryColor':'#cc241d','background':'#282828','mainBkg':'#fbf1c7','secondaryBkg':'#ebdbb2','textColor':'#3c3836','fontSize':'16px'}}}%%
flowchart LR
subgraph Input["ข้อมูลเริ่มต้น
Input Data"]
A[Raw DataFrame]
end
subgraph Process["ประมวลผล
Processing"]
B[GroupBy]
C[Aggregation]
D[Transform]
E[Pivot]
end
subgraph Output["ผลลัพธ์
Output"]
F[Summary Stats
สถิติสรุป]
G[Reports
รายงาน]
H[Enriched Data
ข้อมูลเสริม]
end
A --> B
B --> C
B --> D
B --> E
C --> F
D --> H
E --> G
style A fill:#b8bb26,stroke:#3c3836,stroke-width:2px,color:#282828
style B fill:#fe8019,stroke:#3c3836,stroke-width:2px,color:#282828
style C fill:#d3869b,stroke:#3c3836,stroke-width:2px,color:#282828
style D fill:#d3869b,stroke:#3c3836,stroke-width:2px,color:#282828
style E fill:#d3869b,stroke:#3c3836,stroke-width:2px,color:#282828
style F fill:#83a598,stroke:#3c3836,stroke-width:2px,color:#282828
style G fill:#83a598,stroke:#3c3836,stroke-width:2px,color:#282828
style H fill:#83a598,stroke:#3c3836,stroke-width:2px,color:#282828
Pandas Official Documentation - Group By
Pandas API Reference - pandas.DataFrame.groupby
Pandas Official Documentation - Pivot Tables
Python for Data Analysis โดย Wes McKinney (ผู้สร้าง Pandas)
Pandas Cookbook โดย Theodore Petrou
Real Python - Pandas GroupBy Tutorial
Towards Data Science - Advanced Pandas Aggregation
NumPy Documentation
Matplotlib/Seaborn Documentation
หมายเหตุ: เอกสารนี้เป็นส่วนหนึ่งของคู่มือ Pandas ฉบับสมบูรณ์ สามารถนำไปประยุกต์ใช้กับข้อมูลจริงได้ทันที ตัวอย่าง code ทั้งหมดทดสอบแล้วกับ Pandas version 2.0+