Python pandas i wizualizacja danych PKB z World Bank

Jak wygenerować wykresy wprost z biblioteki Pandas? Dziś postaram się wam przybliżyć pracę z Pandas na przykładzie wizualizacji PKB z danych z banku światowego. Jak na dłoni zobaczymy czy uda nam się kiedyś dogonić Niemcy i czemu pomimo wyższego PKB niż Czechy żyje nam się relatywnie biedniej.

Co jest najcięższego w przetwarzaniu danych? Większość się pewnie zgodzi, że ich wczytywanie i czyszczenie. Ja odkąd pamiętam miałem z tym problemy. W jakiej formie dane by nie były udostępnione i jak wiele staranności nie było przyłożone do ich zebrania to zawsze brakuje jakiś wartości, wkradną się dziwne znaki, liczby w niepoprawnym formacie itp. Chyba każdy z tym walczył. Z tego chaosu może nas wyciągnąć Pandas. Biblioteka, która pozwala na wczytywanie danych do tabeli oraz na późniejsze operowanie na nich.

O Pandas można myśleć jak o bazie danych, gdzie dane przechowywane są w DataFrame (odpowiednik tabeli w sql), na których możemy wykonywać szereg operacji ułatwiających życie: grupowanie, modyfikacje i przekształcenia kolumn, wykonywanie zapytań (wyciąganie danych spełniających zadane warunki) a na koniec także generowanie wykresów.

Jeżeli nie miałeś/miałaś do czynienia z Pandas to warto prześledzić kultowy tutorial 10 minutes to pandas wprowadzający w podstawy filozofii pracy z tą biblioteką. Ja natomiast chcę dziś przedstawić wam Pandas w konkretnym zastosowaniu na przykładzie pracy z danymi z banku światowego. Mam nadzieję, że takie wprowadzenie pozwoli złapać wam także niuanse pracy z danymi i Pandas.

Wizualizacja GDP dla Polski i sąsiadów z World Bank

Ostatnio uczestniczyłem w rozmowie na temat tego, że Niemcy popadają w ruinę i niedługo ich dogonimy. Myślę sobie no w końcu i gdzieś głęboko w poczułem delikatną satysfakcję. W końcu nastanie dziejowa sprawiedliwość i Polska będzie od morza do morza. Jednak szybko spadłem na ziemię i włączył się mój sceptycyzm. Szukając pomysłu na kolejny wpis postanowiłem właśnie zbadać ten temat. Nasza analiza będzie opierała się na jednym z głównych mierników gospodarki czyli PKB, ażeby było ciekawiej to postanowiłem porównać PKB Polski i kilku państw Europejskich.

Ale skąd wziąć dane na temat innych państw, nic prostszego można wykorzystać dane z banku światowego (World Bank) z World Development Indicators.  Są to dane w otwartym formacie zbierane od kilku lat od wielu państw, zawierają one wiele wskaźników ekonomicznych, społecznych itp. informujących o rozwoju danego kraju. Można samemu dokonać ich eksploracji używając online’owego narzędzia do ich przeglądania i wizualizacji. Wybieramy interesujące nas kraje, wskaźniki i zakres data, a następnie w prawym górnym rogu, klikamy przycisk “Download Options” i ściągamy dane w wybranym formacie. Ja do analizy wybrałem:

  • kraje: Polska, Niemcy, Ukraina, Białoruś, Czechy, Słowacja, Węgry, Estonia, Francja, UK
  • wskaźniki: GDP per capita (current US$), GDP per capita growth (annual %), GDP (current US$), GDP growth (annual %)
  • lata: 1990 – 2016 (gdyż tylko takie były dostępne dla wybranych wskaźników)

Plik z danymi GDP wybranych krajów Europejskich

Wczytywanie i przekształcanie danych

Aby zacząć naszą zabawę, w pierwszej kolejności wczytujemy dane z pliku csv. Następnie usuwamy ostatnie 5 wierszy, gdyż zawierają puste wartości i informację o dacie ostatniej aktualizacji danych. Dodatkowo usuwam kolumnę z rokiem 2016, gdyż jak się okazało jest on pusta (brak danych). ‘gdp.replace’  odpowiada na zamianę dwóch kropek, symbolizujących wartości puste, na NaN.

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

gdp = pd.read_csv('./shared/WorldBank/GDP_Poland_neighbours.csv')

#we take only data, not additional informations
gdp = gdp[0:-5]
#delete empty column
del gdp['2016 [YR2016]']
#replace '..' string with nan values
gdp.replace('..', np.nan, inplace=True)

W trakcie dalszej pracy z DataFrame otrzymywałem tajemnicze błędy, nie byłem w stanie stwierdzić co jest nie tak. Dopiero po jakimś czasie postanowiłem sprawdzić typy poszczególnych kolumn.

gdp.dtypes

Country Name      object
Country Code      object
Series Name       object
Series Code       object
1990 [YR1990]     object
1991 [YR1991]     object
1992 [YR1992]     object
1993 [YR1993]     object
1994 [YR1994]     object
1995 [YR1995]     object
1996 [YR1996]    float64
1997 [YR1997]    float64
1998 [YR1998]    float64
1999 [YR1999]    float64
2000 [YR2000]    float64
2001 [YR2001]    float64
2002 [YR2002]    float64
2003 [YR2003]    float64
2004 [YR2004]    float64
2005 [YR2005]    float64
2006 [YR2006]    float64
2007 [YR2007]    float64
2008 [YR2008]    float64
2009 [YR2009]    float64
2010 [YR2010]    float64
2011 [YR2011]    float64
2012 [YR2012]    float64
2013 [YR2013]    float64
2014 [YR2014]    float64
2015 [YR2015]    float64
dtype: objec

i ku mojemu zdziwieniu od 1990 do 1995 typem danych nie był float64 tylko object, stąd postanowiłem dla pewności wszystkie kolumny z latami przekonwertować na wartości numeryczne. W tym celu pobrałem listę kolumn od 4 do końca (czyli wszystkie z latami) i wykorzystując metodę ‘apply’  zaaplikowałem dla każdej wartość funkcję ‘pd.to_numeric’ która dokonuje konwersji na liczbę zmiennoprzecinkową.

# some of the colums are objects, we have to convert to floats, 
#then pivot_table will take them into consideration
col_list = gdp.columns[4:].values
gdp[col_list]=gdp[col_list].apply(pd.to_numeric)

Transformacja dataframe do tabeli przestawnej

W obecnej postaci w każdym wierszu była nazwa kraju, jego kod, nazwa serii danych z World Bank jego kod, a dalej w kolejnych kolumnach lata. Takie ułożenie danych nie było zbyt wygodne więc postanowiłem przeindeksować tabelę z wykorzystaniem funkcji ‘pivot_table’ 

#reindex all table, create pivot view
pv2 = pd.pivot_table(gdp,index=['Series Name','Country Code'], dropna=False, fill_value=0.0)
# set the years
pv2.columns= np.arange(1990,2016)

Ostatecznie z postaci:

wordbank pandas dataframe

do postaci

wordbank pandas pivot table

Czyli w łatwy sposób mogę wyciągną dany wskaźnik ekonomiczy i mam dla niego od razu wszystkie kraje wraz z latami.

Wizualizacja danych wprost z Pandas

Dzięki powyższym zabiegom możemy w łatwy sposób dokonać wizualizacji 4 wybranych wskaźników. Dla ładniejszych wykresów importuje seaborn (o seaborn pisałem ostatnio) i ustawiam paletę kolorów, tak aby każda linia na wykresie była kreślona innym kolorem.  Zachęcam do porównania wykresów z użyciem seaborn i bez.

Rysowanie wprost z pandas jest naprawdę łatwe, wystarczy dla naszej tabeli przestawnej wybrać interesujący nas wskaźnik, następnie transponować dane (funkcja .T) i narysować wykres (‘plot’).

import seaborn as sns
palette = sns.color_palette("Paired", 10)
sns.set_palette(palette)

pv2.loc['GDP (current US$)'].T.plot(alpha=0.75, rot=45)
pv2.loc['GDP per capita (current US$)'].T.plot(alpha=0.8, rot=45)
pv2.loc['GDP per capita (current US$)'].T.plot(alpha=0.75, rot=45)
pv2.loc['GDP growth (annual %)'].T.plot(alpha=0.75, rot=45)

Pierwszy z wykresów nie pozostawia złudzeń, Niemcy są na poziomie 3.5×10^12( 3.5 biliona $) a my ledwo 0.5 biliona. Czyli prawie 7 razy mniej

European countries GDP plot
GDP (current US$), data from World bank

Jeszcze gorzej wypadamy gdy weźmiemy PKB przypadające na jednego mieszkańca, wyprzedzamy jedynie Ukrainę i Białoruś.

European GDP per capita plot
GDP per capita, data from World bank

Czy dogonimy Niemcy w rozwoju na podstawie prostej regresji

Spróbujmy przeprowadzić prostą regresji dla danych PKB, aby zobaczyć czy istnieje szansa że dogonimy kiedyś Niemcy. Tym razem posłużymy się funkcją ‘lmplot’  z seaborn, z tym że musimy dane doprowadzić do formy szeregu czasowego. Z danych w postaci tabeli z poszczególnymi krajami jako kolumny, musimy stworzyć tabelę w której będziemy mieli tylko trzy kolumny [lata, kraj, wartość PKB]. Dokonujemy tego w wyniku szeregu operacji, usuwania indeksu, bo nasza tabela na początku jest indeksowana latami (unikalne wiersze), zmiany nazwy kolumny. Kluczową operacją jest tutaj funkcja ‘melt’ które przenosi dane z kolumn i dokłada je do kolejnych wierszy. Dzięki czemu jesteśmy w stanie dokonać następującego przekształcenia. Na załączonych obrazach pominąłem część kolumn i wierszy, ale mam można się domyśleć:

wordbank pandas pivot table
wordbank pandas dataframe melt
#seaborn plots
plot_data = pv2.loc['GDP (current US$)'].T.reset_index()
plot_data.rename(columns={'index':'Years'}, inplace=True)
# unpivot the data, change from table view, where we have columns for each 
# country, to big long time series data, [year, country code, value]
melt_data = pd.melt(plot_data, id_vars=['Years'],var_name='Country')
melt_data.rename(columns={'value':'GDP'}, inplace=True)
sns.lmplot(x="Years", y="GDP", hue="Country", data=melt_data, palette="Set1");

Powinniśmy otrzymać wykres:

pandas seaborn lmplot wordbank gdp

Widać na nim jak na dłoni że Niemcy, UK i Francja mają podobny poziom wzrostu (ich linie są równoległe), czwarta Polska ma zdecydowanie mniejszy kąt. Wierząc liczbom należy dojść do wniosku, że nigdy nie dogonimy Niemiec.

Podsumowanie

Dzięki danym z banku światowego mogliśmy zapoznać się z biblioteką Pandas i wygenerować kilka ciekawych wykresów. Co prawda wizualizacje są w pesymistycznym tonie, ale mam nadzieję, że nie zaburzy to wam frajdy z wizualizacji PKB dla krajów ościennych.

Kod możesz ściągnąć z ksopyla@GitHub.

Jeżeli uważasz ten wpis za wartościowy to Zasubskrybuj bloga. Dostaniesz informacje o nowych artykułach.

Join 68 other subscribers

10 Comments Python pandas i wizualizacja danych PKB z World Bank

  1. Maciek

    Nareszcie polski poradnik czegoś więcej, niż informatycznego smęcenia i trywialnych przykladów z książek. 🙂

    Reply
  2. Paweł

    Jest:
    pv2.loc[‘GDP per capita (current US$)’].T.plot(alpha-0.8, rot=45)

    Powinno być
    pv2.loc[‘GDP per capita (current US$)’].T.plot(alpha=0.8, rot=45)

    Zmiana “-” na “=”

    Pozdrawiam, świetny blog!

    Reply
  3. Kamil

    Mam pytanie dotyczące pd.read_csv. Otóż po wczytaniu pliku i użyciu funkcji shape pokazuje mi się 265 wierszy. Wczytując ten sam plik do excela widzę 752 wiersze. Dlaczego w pierwszym przypadku funkcja nie wczytuje całego pliku?

    Reply
  4. Daniel

    Panie Krzysztofie,

    świetny wpis oparty na realnych danych – daje inspirację do własnych analiz i wniosków. Jednak miejmy nadzieję, że w przypadku doganiania przez Polskę pozostałych krajów rozwiniętych zadziała efekt konwergencji 🙂

    Pozdrawiam

    Reply
    1. ksopyla

      Dzieki Daniel. A co do analiz to życie ma to do siebie, że zaskakuje i nie daje się tak łatwo przewidzieć. Wszystko się może zdarzyć 🙂
      Temat danych z wordbank’u jest tu głównie nośnikiem wiedzy, którą chciałem przekazać i jak można pracować z pandas.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.