0Pricing
Pandas & NumPy Academy · Lekcja

stack i unstack z MultiIndex

Przenoś najbardziej wewnętrzny poziom kolumn do indeksu wierszy za pomocą stack() i odwracaj tę operację za pomocą unstack().

stack i unstack z MultiIndex to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Pandas & NumPy Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.

Wprowadzenie do stack i unstack

Funkcje stack() i unstack() to narzędzia Pandas do zmiany kształtu danych, które przenoszą dane między indeksem wierszy a indeksem kolumn. Są szczególnie przydatne podczas pracy z obiektami DataFrame, które mają MultiIndex na jednej z osi. Funkcja stack() przenosi najbardziej wewnętrzny poziom indeksu kolumn do najbardziej wewnętrznego poziomu indeksu wierszy, natomiast unstack() wykonuje operację odwrotną.

stack(): kolumny na wiersze

DataFrame.stack() przenosi najbardziej wewnętrzny poziom etykiet kolumn do najbardziej wewnętrznego poziomu indeksu wierszy, tworząc dłuższy i węższy wynik. Jeśli pierwotny DataFrame miał proste kolumny (bez MultiIndex), wynikiem jest Series z MultiIndex. Jeśli kolumny miały wiele poziomów, funkcja stack() zmniejsza ich liczbę o jeden.

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(): wiersze na kolumny

Series.unstack() (lub DataFrame.unstack()) jest odwrotnością funkcji stack(). Pobiera najbardziej wewnętrzny poziom indeksu wierszy i przenosi go do nowych etykiet kolumn, tworząc szerszy wynik. Funkcjonalnie przypomina to funkcję pivot(), ale operuje bezpośrednio na indeksie, a nie na wartościach kolumn.

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!

Wybieranie poziomu do operacji stack

W przypadku obiektów DataFrame z MultiIndex na kolumnach funkcja stack(level) pozwala wybrać poziom, który ma zostać przeniesiony. Należy przekazać numer poziomu (0 oznacza poziom najbardziej zewnętrzny, -1 najbardziej wewnętrzny i jest wartością domyślną) albo nazwę poziomu. Analogicznie funkcja unstack(level) wybiera poziom indeksu wierszy, który ma zostać przeniesiony do kolumn. Tak precyzyjna kontrola jest niezbędna podczas pracy ze złożonymi hierarchicznymi strukturami danych.

# 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() na określonych poziomach wierszy

Gdy DataFrame ma MultiIndex wierszy (co często ma miejsce po użyciu funkcji groupby() dla wielu kolumn), można zastosować unstack() do określonego poziomu wierszy, aby rozłożyć go na kolumny. Jest to bardzo częsty wzorzec służący do tworzenia podsumowań w stylu tabel przestawnych bez jawnego wywoływania funkcji 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

Obsługa brakujących wartości w stack/unstack

Gdy wywołana zostanie funkcja unstack(), a nie każda kombinacja indeksu wierszy występuje dla każdego poziomu kolumn, Pandas wstawia w brakujące komórki wartość NaN. Z kolei funkcja stack() domyślnie usuwa wiersze, które w całości zawierają NaN. Można to kontrolować za pomocą parametru dropna: należy przekazać stack(dropna=False), aby zachować wiersze z wartościami 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(), a następnie obliczenia na wierszach

Skuteczny wzorzec polega na użyciu funkcji stack() do przekształcenia szerokiego DataFrame tak, aby kolumny stały się wierszami, wykonaniu operacji wierszowej, takiej jak filtrowanie lub groupby, a następnie użyciu unstack() w celu powrotu do formatu szerokiego. Eliminuje to konieczność pisania pętli przetwarzających kolumny pojedynczo, a kod pozostaje zwektoryzowany i czytelny. Jest to szczególnie przydatne, gdy tę samą transformację należy zastosować jednocześnie do każdej kolumny.

# 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() do tworzenia wykresów

Podobnie jak melt(), funkcja stack() przekształca dane do formatu długiego, którego oczekują biblioteka Seaborn i wiele funkcji pomocniczych Matplotlib. Główna różnica polega na tym, że stack() działa na indeksie kolumn i zachowuje strukturę MultiIndex, natomiast melt() tworzy płaski DataFrame w formacie długim. Obie funkcje prowadzą do podobnego sposobu tworzenia wykresów.

# 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() do zmiany kolejności indeksów

Po użyciu funkcji stack najbardziej wewnętrzny poziom wierszy odpowiada pierwotnej nazwie kolumny. Czasami pożądane jest, aby poziom zewnętrzny zawierał nazwę zmiennej, a poziom wewnętrzny — pierwotny indeks wierszy. Należy użyć funkcji swaplevel() na MultiIndex, aby zamienić kolejność dwóch poziomów, a następnie funkcji sort_index(), aby przywrócić uporządkowaną kolejność.

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

Kiedy używać stack, melt i pivot

Funkcji stack() należy używać podczas pracy z obiektami DataFrame z kolumnami MultiIndex, gdy chcą Państwo zmniejszyć liczbę poziomów kolumn o jeden. Funkcji melt() należy używać w przypadku płaskiego DataFrame, gdy chcą Państwo przejść z formatu szerokiego do długiego i kontrolować, które kolumny staną się wierszami. Funkcje pivot()/pivot_table() służą do przejścia z formatu długiego z powrotem do szerokiego. Te trzy narzędzia obejmują wszystkie potrzeby związane ze zmianą kształtu danych szerokich i długich w 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)

Praktyczne podsumowanie: ściąga dotycząca zmiany kształtu danych

Oto zwięzły model mentalny: stack() — kolumny są składane do wierszy, a DataFrame staje się węższy i wyższy. unstack() — wiersze są rozwijane do kolumn, a DataFrame staje się szerszy i niższy. melt() — nazwane kolumny są składane do pary klucz–wartość (dwóch nowych kolumn). pivot_table() — kolumna klucza–wartości jest rozwijana do wielu kolumn. Wszystkie cztery operacje są odwracalne, a wybór kierunku sprowadza się do ustalenia, czy docelowa analiza lepiej działa na danych w formacie szerokim, czy długim.

# 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)

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat funkcji stack i unstack oraz MultiIndex z tej lekcji.

Podsumowanie lekcji

W tej lekcji nauczyli się Państwo, że funkcja stack() przenosi etykiety kolumn do indeksu wierszy, tworząc dłuższy i węższy wynik; unstack() wykonuje operację odwrotną, przenosząc poziom indeksu wierszy do kolumn; obie funkcje działają ze strukturami MultiIndex tworzonymi przez operacje groupby; a swaplevel() umożliwia zmianę kolejności poziomów indeksu. Następnie poznają Państwo funkcję pd.crosstab() do szybkiego tworzenia tabel częstości dla kolumn kategorycznych.

Często zadawane pytania

Czy lekcja „stack i unstack z MultiIndex” jest bezpłatna?

Tak — pełny tekst „stack i unstack z MultiIndex” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Pandas & NumPy Academy, przejdź na CoddyKit PRO. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „stack i unstack z MultiIndex”?

Przenoś najbardziej wewnętrzny poziom kolumn do indeksu wierszy za pomocą stack() i odwracaj tę operację za pomocą unstack(). Ćwiczysz Pandas & NumPy Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Pandas & NumPy Academy?

Nie wymagamy żadnego doświadczenia. Pandas & NumPy Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „stack i unstack z MultiIndex”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Pandas & NumPy Academy?

Tak. Każda lekcja Pandas & NumPy Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. pivot_table: tabulacja krzyżowa
  2. melt: format szeroki na długi
  3. stack i unstack z MultiIndex
  4. crosstab do tabel częstości
← Powrót do Pandas & NumPy Academy