#023 Wykres warstwowy (area chart)

Wykres warstwowy (czasami zwany też wykresem powierzchniowym) jest bardzo podobny do wykresu liniowego i przedstawia ewolucję zmiennej numerycznej. Co do zasady w przypadku tego wykresu oś  X reprezentuje czas (lub rzadziej zmienną uporządkowaną). Natomiast na osi Y przedstawione są wartości innej zmiennej. Punkty danych są połączone linią prostą, a obszar między osią x a linią jest wypełniony kolorem lub cieniowaniem.

Znacie zasadę data-ink ratio? Jest to koncepcja stworzona przez Edwarda Tufte. Mówi o stosunku danych do ilości atramentu zużytego podczas drukowania. Zachęca twórców wykresów do sprawdzenia, czy wszystkie elementy na wykresie są istotne dla przesłania wykresu. Z tego powodu można spotkać się z krytyką tego wykresu. Nie da się zaprzeczyć, że usunięcie obszaru pod krzywą sprawiłoby utworzenie wykresu liniowego pokazującego te same informacje. Jednak moim zdaniem wykres warstwowy bardzo dobrze pokazuje ewolucję, a wypełniony obszar sprawia, że trend w danych jest jeszcze bardziej widoczny.

Dodatkowo wykres świetnie nadaje się w przypadku, gdy mamy dłuższą historię, gdzie wykres kolumnowy nie byłby już zbyt czytelny ze względu na wielość występujących kolumn.

Wadą tych wykresów jest mniejsza precyzja. Wykresy warstwowe mogą być mniej dokładne niż inne typy wykresów, takie jak wykresy liniowe czy wykresy słupkowe, ponieważ trudno jest wskazać dokładną wartość punktu na wykresie. Występują również trudności w rozróżnianiu serii. Na przykład, gdy na tym samym wykresie warstwowym jest wyświetlanych wiele serii danych, rozróżnienie między nimi może być trudne i problematyczne, gdy obszary różnych szeregów zachodzą na siebie. Na szczęście problem ten rozwiązują skumulowane wykresy warstwowe.

Skumulowany wykres warstwowy

Skumulowany wykres warstwowy jest rozszerzeniem podstawowego wykresu warstwowego. Przedstawia ewolucję wartości kilku grup na tej samej grafice. Wartości każdej grupy wyświetlamy na wykresie jedną nad drugą, co pozwala sprawdzić na tej samej figurze ewolucję zarówno sumy zmiennej numerycznej, jak i ważności każdej grupy. Taka wizualizacja danych może ułatwić porównywanie względnych rozmiarów różnych serii danych i obserwowanie, jak zmieniają się one w czasie.

Skumulowane wykresy warstwowe mogą być również wykorzystywane do przedstawiania danych procentowych, na przykład procentowego udziału poszczególnych kategorii w zbiorze danych.

Kod w Python

Narysujmy wykresy wykorzystując najbardziej podstawową bibliotekę wykorzystywaną do wizualizacji, czyli matplotlib.

Wyczytajmy najpierw biblioteki:

import pandas as pd
import seaborn as sns

from matplotlib import pyplot as plt
from platform import python_version

from matplotlib import __version__ as plt_ver

pd.options.display.max_columns = 100

print(f'python: {python_version()}')
print(f'\nseaborn: {sns.__version__}')
print(f'pandas: {pd.__version__}')
print(f'matplotlib: {plt_ver}')

Pobierzmy na samym początku dane. Znalazłem ciekawe dane z Nowej Zelandii z informacją, ile w danym roku rodziło się dzieci pogrupowane po imionach dzieci od 1900 roku!

# download data from page: https://catalogue.data.govt.nz/dataset/baby-name-popularity-over-time
url="https://catalogue.data.govt.nz/dataset/01ee87cd-ecf8-44a1-ad33-b376a689e597/resource/0b0b326c-d720-480f-8f86-bf2d221c7d3f/download/baby-names-2022-01-07.csv"
df = pd.read_csv(url, encoding="latin")
df.head()

Jako dumny tata dwójki dziewczynek pomyślałem, że możemy przyjrzeć się tylko płci pięknej.

df_girls = df[df.Sex=="F"]
df_yearly = df_girls.groupby(['Year'])['Count'] /
                    .agg(['sum', 'count']) /
                    .reset_index()
df_yearly.head(5)

Przygotujmy teraz wykres warstwowy pokazujący liczbę imion żeńskich w czasie.

#set seaborn style
sns.set_theme()
 
#create area chart
plt.figure(figsize=(15,6))
plt.stackplot(df_yearly['Year'], 
              df_yearly['sum'])

plt.title('Girls baby name by years', fontsize=15)
plt.xlabel('Years')
plt.ylabel('Number of names')

#display area chart
plt.show()

Mając duszę analityka danych sprawdźmy jeszcze, wykorzystując wykres warstwowy, jak wygląda liczba unikalnych imion w czasie.

#create area chart
plt.figure(figsize=(15,6))
plt.stackplot(df_yearly['Year'], 
              df_yearly['count'], 
              color='crimson')

plt.title('Girls baby name by distinct names', fontsize=15)
plt.xlabel('Years')
plt.ylabel('Number of distinct names')

#display area chart
plt.show()

Widzimy, że roczna liczba nowourodzonych dziewczynek od okolo 1960 systematycznie spada cały czas. Natomiast widzimy, że z roku na rok w Nowej Zelandii nadawane są coraz bardziej zróżnicowane imiona.

Skumulowany wykres warstwy

Wybierzmy teraz kilka najczęściej występujących imion na przestrzeni tego okresu. Poniżej w kodzie znajdziesz zaproponowaną przeze mnie listę 9 imion. Narysujmy dla nich skumulowany wykres warstwowy:

labels=['Margaret', 'Mary', 'Sarah', 'Emily','Sophie',
        'Olivia','Christine','Lisa','Michelle']

df_pivot = df_girls.pivot(index="Year", 
                          columns=["Name"],
                          values="Count") \
                   .fillna(0) \
                   .reset_index()

plt.figure(figsize=(15,6))
plt.stackplot(df_pivot['Year'],
              df_pivot['Margaret'],
              df_pivot['Mary'],
              df_pivot['Sarah'],
              df_pivot['Emily'],
              df_pivot['Sophie'],
              df_pivot['Olivia'],
              df_pivot['Christine'],
              df_pivot['Lisa'],
              df_pivot['Michelle'],
              labels=labels,
             )

plt.title('Girls baby name by years', fontsize=15)
plt.xlabel('Years')
plt.ylabel('Number of names')

#add legend
plt.legend()

plt.show()

Moim zdaniem w przejrzysty sposób widzimy na wykresie najbardziej popularne per okres nadawane imiona dziewczynkom.

Odmianą skumulowanego wykresu warstwowego jest procentowy skumulowany wykres warstwowy. Różnica polega na tym, że wartości każdej grupy są znormalizowane w każdym znaczniku czasu.

# We need to transform the data from raw data to percentage (fraction)
df_perc = df_pivot[labels].divide(df_pivot[labels].sum(axis=1), 
                                  axis=0)

plt.figure(figsize=(15,6))
plt.stackplot(df_pivot['Year'],
              df_perc['Margaret'],
              df_perc['Mary'],
              df_perc['Sarah'],
              df_perc['Emily'],
              df_perc['Sophie'],
              df_perc['Olivia'],
              df_perc['Christine'],
              df_perc['Lisa'],
              df_perc['Michelle'],
              labels=labels,
             )

plt.title('Girls baby name by years', fontsize=15)
plt.xlabel('Years')
plt.ylabel('Percent for names')
plt.legend()

plt.show()

Niemniej chciałem jeszcze Ci jeszcze jedną ciekawostkę. Alternatywą dla wykresu skumulowanego może być narysowanie każdej zmiennej osobno:

# alternative chart
f, axs = plt.subplots(3,3,figsize=(15,10))
colors=['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', 
        '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
 
i = 1
for name in labels:
    plt.subplot(3, 3, i)
     
    plt.stackplot(df_pivot['Year'],
                  df_perc[name],
                  color=colors[i-1]
                 )
    plt.xticks([])
    plt.title(f'{name}', fontsize=15)
    
     
    i = i+1

Mam nadzieję, że znasz już wady i zalety wykresu warstwowego!

Pozdrawiam z całego serducha,

podpis Mirek

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *