0Pricing
Pandas & NumPy Academy · บทเรียน

stack และ unstack กับ MultiIndex

หมุนระดับคอลัมน์ชั้นในสุดมาเป็นดัชนีแถวด้วย stack() และย้อนกลับด้วย unstack()

stack และ unstack กับ MultiIndex เป็นบทเรียน Pandas & NumPy Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Pandas & NumPy Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน

บทนำเกี่ยวกับ stack และ unstack

stack() และ unstack() เป็นเครื่องมือปรับรูปของ Pandas ที่ใช้ย้ายข้อมูลระหว่าง ดัชนีแถว กับ ดัชนีคอลัมน์ เครื่องมือเหล่านี้มีประโยชน์เป็นพิเศษเมื่อทำงานกับ DataFrames ที่มี MultiIndex บนแกนใดแกนหนึ่ง stack() จะนำระดับคอลัมน์ชั้นในสุดมาหมุนเป็นระดับแถวชั้นในสุด ส่วน unstack() จะทำย้อนกลับกัน

stack(): จากคอลัมน์เป็นแถว

DataFrame.stack() จะเปลี่ยนระดับชั้นในสุดของป้ายกำกับคอลัมน์ให้เป็นระดับชั้นในสุดของดัชนีแถว ทำให้ได้ผลลัพธ์ที่มีแถวยาวขึ้นและคอลัมน์แคบลง หาก DataFrame เดิมมีคอลัมน์แบบง่าย (ไม่ใช่หลายระดับ) ผลลัพธ์จะเป็น Series ที่มี MultiIndex หากคอลัมน์มีหลายระดับ stack() จะลดจำนวนระดับของคอลัมน์ลงหนึ่งระดับ

import pandas as pd

df = pd.DataFrame({
    'Math': [85, 90, 78],
    'Science': [92, 88, 95]
}, index=['Alice', 'Bob', 'Carol'])

print(df)
#        Math  Science
# Alice    85       92
# Bob      90       88
# Carol    78       95

stacked = df.stack()
print(stacked)
# Alice    Math       85
#          Science    92
# Bob      Math       90
#          Science    88
# Carol    Math       78
#          Science    95
# dtype: int64

unstack(): จากแถวเป็นคอลัมน์

Series.unstack() (หรือ DataFrame.unstack()) เป็นการทำงานย้อนกลับของ stack() โดยนำระดับชั้นในสุดของดัชนีแถวมาหมุนเป็นป้ายกำกับคอลัมน์ใหม่ ทำให้ได้ผลลัพธ์ที่กว้างขึ้น การทำงานนี้คล้ายกับ pivot() แต่ทำงานโดยตรงกับดัชนีแทนค่าภายในคอลัมน์

stacked = df.stack()
print(type(stacked))  # Series with MultiIndex

# Restore the original wide format
df_restored = stacked.unstack()
print(df_restored)
#        Math  Science
# Alice    85       92
# Bob      90       88
# Carol    78       95

# Identical to the original df!

การเลือกระดับที่จะใช้กับ stack

สำหรับ DataFrames ที่มี MultiIndex บนคอลัมน์ stack(level) ช่วยให้คุณเลือกระดับที่จะหมุนได้ คุณสามารถส่งหมายเลขระดับ (0 สำหรับระดับนอกสุด, -1 สำหรับระดับในสุด ซึ่งเป็นค่าเริ่มต้น) หรือชื่อระดับก็ได้ ในทำนองเดียวกัน unstack(level) ใช้เลือกระดับของดัชนีแถวที่จะหมุนเป็นคอลัมน์ การควบคุมในรายละเอียดระดับนี้จำเป็นอย่างยิ่งต่อการจัดการโครงสร้างข้อมูลแบบลำดับชั้นที่ซับซ้อน

# MultiIndex columns
arrays = [['Math', 'Math', 'Science', 'Science'],
          ['Q1', 'Q2', 'Q1', 'Q2']]
multi_cols = pd.MultiIndex.from_arrays(arrays, names=['subject', 'quarter'])

df_multi = pd.DataFrame([[85, 90, 92, 88], [78, 80, 95, 91]],
                        index=['Alice', 'Bob'], columns=multi_cols)

# Stack the 'quarter' level (innermost, level=-1)
print(df_multi.stack(level='quarter').head())

unstack() กับระดับแถวที่ระบุ

เมื่อ DataFrame มี MultiIndex บนแถว ซึ่งเป็นกรณีที่พบได้บ่อยหลังใช้ groupby() กับหลายคอลัมน์ คุณสามารถใช้ unstack() กับระดับแถวที่ต้องการ เพื่อกระจายระดับนั้นไปตามคอลัมน์ รูปแบบนี้พบได้บ่อยมากในการสร้างสรุปในลักษณะตารางไขว้ โดยไม่ต้องเรียกใช้ pivot_table() โดยตรง

# GroupBy produces MultiIndex rows
df2 = pd.DataFrame({
    'region': ['East', 'East', 'West', 'West'],
    'product': ['A', 'B', 'A', 'B'],
    'sales': [100, 150, 120, 200]
})

# MultiIndex result from groupby
multi = df2.groupby(['region', 'product'])['sales'].sum()
print(multi)

# Unstack the product level into columns
wide = multi.unstack('product')
print(wide)
# product    A    B
# region
# East     100  150
# West     120  200

การจัดการค่าที่หายไปใน stack/unstack

เมื่อเรียกใช้ unstack() แล้วชุดค่าผสมของดัชนีแถวบางชุดไม่มีอยู่ในทุกระดับคอลัมน์ Pandas จะเติมเซลล์ที่ขาดหายด้วย NaN ในทางกลับกัน stack() จะละทิ้งแถวที่เป็น NaN ทั้งหมดโดยค่าเริ่มต้น คุณควบคุมการทำงานนี้ได้ด้วยพารามิเตอร์ dropna โดยส่ง stack(dropna=False) เพื่อเก็บแถวที่มี NaN ไว้

# Incomplete data: West has no product B
df3 = df2[df2['product'] != 'B'].copy()
multi3 = df3.groupby(['region', 'product'])['sales'].sum()

wide3 = multi3.unstack('product', fill_value=0)
print(wide3)
# product    A    B
# region
# East     100    0  <- B filled with 0 instead of NaN
# West     120    0

stack() แล้วคำนวณกับแถว

รูปแบบการทำงานที่ทรงพลังคือใช้ stack() กับ DataFrame รูปแบบกว้างเพื่อเปลี่ยนคอลัมน์เป็นแถว ใช้การดำเนินการกับแถว เช่น การกรองหรือ groupby แล้วใช้ unstack() เพื่อกลับไปเป็นรูปแบบกว้าง วิธีนี้ไม่จำเป็นต้องเขียนลูปแยกทีละคอลัมน์ และทำให้โค้ดเป็นเวกเตอร์และอ่านได้ง่าย โดยเฉพาะเมื่อจำเป็นต้องใช้การแปลงแบบเดียวกันกับทุกคอลัมน์พร้อมกัน

# Normalise each column by its column mean using stack/compute/unstack
normalised = (
    df.stack()
      .groupby(level=1)
      .transform(lambda s: (s - s.mean()) / s.std())
      .unstack()
)
print(normalised.round(2))
#        Math  Science
# Alice  0.0     0.39
# Bob    1.13   -1.09
# Carol -1.13    0.71

stack() สำหรับการสร้างกราฟ

เช่นเดียวกับ melt() stack() จะแปลงข้อมูลเป็นรูปแบบยาว ซึ่งเป็นรูปแบบที่ Seaborn และตัวช่วยจำนวนมากของ Matplotlib ต้องการ ความแตกต่างหลักคือ stack() ทำงานกับดัชนีคอลัมน์และคงโครงสร้าง MultiIndex ไว้ ขณะที่ melt() จะสร้าง DataFrame รูปแบบยาวแบบแบน ทั้งสองวิธีนำไปสู่กระบวนการสร้างกราฟที่คล้ายกัน

# Prepare data for line plot using stack
long = df.stack().reset_index()
long.columns = ['student', 'subject', 'score']
print(long)
#   student  subject  score
# 0   Alice     Math     85
# 1   Alice  Science     92
# ...

# Ready for: sns.barplot(data=long, x='student', y='score', hue='subject')

swaplevel() สำหรับจัดลำดับดัชนีใหม่

หลังการใช้ stack ระดับแถวชั้นในสุดจะเป็นชื่อคอลัมน์เดิม บางครั้งคุณอาจต้องการให้ระดับนอกสุดเป็นชื่อตัวแปร และระดับในสุดเป็นดัชนีแถวเดิม ใช้ swaplevel() กับ MultiIndex เพื่อสลับลำดับของสองระดับ แล้วใช้ sort_index() เพื่อจัดลำดับให้เรียบร้อยอีกครั้ง

stacked = df.stack()  # MultiIndex: (student, subject)
swapped = stacked.swaplevel()  # MultiIndex: (subject, student)
swapped = swapped.sort_index()
print(swapped)
# subject  student
# Math     Alice      85
#          Bob        90
#          Carol      78
# Science  Alice      92
#          Bob        88
#          Carol      95

ควรใช้ stack, melt หรือ pivot เมื่อใด

เลือกใช้ stack() เมื่อทำงานกับ DataFrame ที่มีคอลัมน์แบบ MultiIndex และต้องการลดระดับคอลัมน์ลงหนึ่งระดับ เลือกใช้ melt() เมื่อมี DataFrame แบบแบนและต้องการแปลงจากรูปแบบกว้างเป็นรูปแบบยาว โดยควบคุมได้ว่าจะเปลี่ยนคอลัมน์ใดให้เป็นแถว เลือกใช้ pivot()/pivot_table() เพื่อแปลงจากรูปแบบยาวกลับเป็นรูปแบบกว้าง เครื่องมือทั้งสามนี้ครอบคลุมความต้องการปรับรูปแบบกว้างและยาวทั้งหมดใน Pandas

# Decision guide (comment, not executable standalone):
# MultiIndex columns -> want fewer levels: use stack()
# Flat wide -> need long format for plotting/ML: use melt()
# Long -> need wide summary table: use pivot_table()
# Wide -> back to long: use melt() or stack()

# Example: stack when you have pivot_table output (MultiIndex cols)
tbl = df2.groupby(['region', 'product'])['sales'].sum().unstack()
long_again = tbl.stack().rename('sales').reset_index()
print(long_again)

สรุปเชิงปฏิบัติ: สรุปจำง่ายเรื่องการปรับรูป

ต่อไปนี้คือแนวคิดสั้น ๆ ที่ควรจำ: stack() — คอลัมน์ถูกรวมเป็นแถว ทำให้ DataFrame แคบลงและสูงขึ้น unstack() — แถวถูกขยายเป็นคอลัมน์ ทำให้ DataFrame กว้างขึ้นและเตี้ยลง melt() — คอลัมน์ที่มีชื่อจะถูกรวมเป็นคู่คีย์และค่า (คอลัมน์ใหม่สองคอลัมน์) pivot_table() — คอลัมน์คีย์และค่าจะขยายเป็นหลายคอลัมน์ เครื่องมือทั้งสี่สามารถแปลงกลับไปมาได้ และการรู้ว่าควรใช้ทิศทางใดก็ขึ้นอยู่กับการตัดสินใจว่าการวิเคราะห์เป้าหมายเหมาะกับรูปแบบกว้างหรือรูปแบบยาวมากกว่า

# stack/unstack cycle
df_wide = df.copy()             # wide format
df_long = df_wide.stack()       # long via stack
df_wide2 = df_long.unstack()    # back to wide

# melt/pivot cycle
df_melted = df_wide.melt(id_vars=[])    # wide -> long
# df_pivoted = df_melted.pivot(...)     # long -> wide

print('Original shape:  ', df_wide.shape)
print('After stack:     ', df_long.shape)
print('After unstack:   ', df_wide2.shape)

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจเกี่ยวกับ stack และ unstack กับ MultiIndex จากบทเรียนนี้

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า stack() หมุน ป้ายกำกับคอลัมน์ให้เป็นดัชนีแถว เพื่อสร้างผลลัพธ์ที่มีแถวยาวขึ้นและคอลัมน์แคบลง ส่วน unstack() จะทำย้อนกลับกัน โดยหมุนระดับของดัชนีแถวให้เป็นคอลัมน์ ทั้งสองเครื่องมือทำงานกับโครงสร้าง MultiIndex ที่เกิดจากการดำเนินการ groupby และ swaplevel() ช่วยให้คุณจัดลำดับระดับของดัชนีใหม่ได้ ต่อไปเราจะสำรวจ pd.crosstab() สำหรับสร้างตารางความถี่อย่างรวดเร็วระหว่างคอลัมน์ประเภทหมวดหมู่

คำถามที่พบบ่อย

บทเรียน “stack และ unstack กับ MultiIndex” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “stack และ unstack กับ MultiIndex” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Pandas & NumPy Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “stack และ unstack กับ MultiIndex”

หมุนระดับคอลัมน์ชั้นในสุดมาเป็นดัชนีแถวด้วย stack() และย้อนกลับด้วย unstack() คุณปฏิบัติ Pandas & NumPy Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Pandas & NumPy Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Pandas & NumPy Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “stack และ unstack กับ MultiIndex” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Pandas & NumPy Academy นี้ได้ไหม

ได้ บทเรียน Pandas & NumPy Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. pivot_table: ตารางไขว้
  2. melt: จากรูปแบบกว้างเป็นรูปแบบยาว
  3. stack และ unstack กับ MultiIndex
  4. crosstab สำหรับตารางความถี่
← กลับไปที่ Pandas & NumPy Academy