Kuviot Pythonilla 1

Tässä artikkelissa perehdyn kuvioiden laatimisen (pylväskuviot) alkeisiin. Tämän artikkelin ohjelmakoodin ja tulosteet löydät GitHubista:

https://github.com/taanila/tilastoapu/blob/master/kuviot1.ipynb

Jos kopioit koodia itsellesi, niin kannattaa käyttää GitHubia. Tästä artikkelista kopioidut koodit eivät välttämättä toimi oikein.

Oletan, että lukijalla on asennettuna Anaconda ja sen mukana tuleva Jupyter notebook.

Pandas-kirjaston dataframe-tietorakenne on keskeinen datojen analysoinnissa: avaan analysoitavan datan dataframeen ja lasketut tulostaulukot ovat enimmäkseen dataframe-muotoisia. Tässä ja muissa kuvioita käsittelevissä artikkeleissani tarkastelen kuvioiden luomista dataframe-muotoisesta datasta.

Matplotlib

Kuvioiden luomisen kulmakivi on matplotlib-kirjasto. Yleensä riittää, että otan käyttöön matplotlib.pyplot-kirjaston (ja tietenkin pandas-kirjaston):

import pandas as pd
import matplotlib.pyplot as plt

Jos käytän Jupyter-notebookia, niin suoritan myös komennon:

%matplotlib inline

Tämän ansiosta kuviot tulostuvat Jupyter-notebookiin ilman erillistä tulostuskomentoa.

Yksinkertainen pylväskuvio

Ensimmäisenä esimerkkinä kuvaan yksinkertaisen myyntilukuja sisältävän taulukon pylväskuviona. Luon myynnit-nimisen dataframen, jossa on neljän eri alueen myyntiluvut:

raw_data={'Alue': ['Helsinki', 'Turku', 'Tampere', 'Oulu'],
    'Myynti': [1321847, 852669, 1032199, 568230]}
 myynnit = pd.DataFrame(raw_data)
 myynnit.index = myynnit['Alue']
 myynnit

Yksinkertaisimmillaan luon vaakapylväskuvion myynnit-dataframen sisällöstä komennolla:

myynnit.plot.barh()

kuviot1

Kuvion muotoilu

Kuvion ulkoasuun vaikutan nopeimmin vaihtamalla tyyliä. Tarjolla olevien tyylien nimet näen komennolla plt.style.available. Tyylin vaihto esimerkiksi tyyliin ’ggplot’ onnistuu komennolla plt.style.use(’ggplot’).

Jos haluan räätälöidä kuviota yksilöidymmin, niin tallennan kuvion luonnin palauttaman Axes-objektin muuttujan arvoksi. Axes-objektin kautta voin muotoilla kuviota monin tavoin. Seuraavassa

  • otan käyttöön ’ggplot’-tyylin
  • järjestän myynnit suuruusjärjestykseen ennen plot.barh-komentoa
  • lisään kuvioon pääotsikon (title) ja poistan selitteen (legend) näkyviltä
  • tallennan kuvion luonnin palauttaman Axes-objektin ax-nimiseen muuttujaan
  • määritänn otsikon x-akselille (xlabel) ja tyhjennän y-akselin otsikon (ylabel)
  • muotoilen x-akselin luvut miljooniksi euroiksi (jos tähän liittyvä koodi vaikuttaa esoteerisiltä, niin siltä se minunkin mielestäni aluksi vaikutti).
plt.style.use('ggplot')
ax=myynnit.sort_values(by='Myynti').plot.barh
   (title='Myynti vuonna 2017', legend=False)
ax.set(xlabel='Miljoonaa euroa', ylabel='')
vals = ax.get_xticks()
ax.set_xticklabels(['{:.1f}'.format(x/1000000) for x in vals])

kuviot2

Seuraavaksi lisään dataframeen prosenttiosuudet kokonaismyynnistä ja esitän prosenttiosuudet pylväskuviona:

n=myynnit['Myynti'].sum()
myynnit['%'] = myynnit['Myynti'] / n * 100
ax=myynnit.sort_values(by='%')['%'].plot.barh
   (title='Osuus kokonaismyynnistä vuonna 2017', legend=False, 
   width=0.7, color='C0')
ax.set(xlabel='%', ylabel='')
vals = ax.get_xticks()
ax.set_xticklabels(['{:.0f} %'.format(x) for x in vals])

kuviot3

Lisämääritys width=0.7 vaikuttaa pylväiden leveyteen ja samalla pylväiden väliseen tyhjään tilaan. Oletus on width=0.5. Mitä suurempi arvo sitä lähempänä pylväät ovat toisiaan. Jos width=1, niin pylväät ovat kiinni toisissaan.

Outo värimääritys color=’C0′ vaatinee selitystä. Jos teen kuvion vain yhdestä dataframen sarakkeesta (esimerkiksi myynnit[’%’]) niin kyseessä ei ole enää dataframe, vaan series. Tällöin jokainen pylväs esitetään omalla värillään (vanhemmissa versioissa tällaista ominaisuutta ei ollut). Verkkokeskusteluiden perusteella on epäselvää, onko kyseessä virhe vai tarkoituksellinen ominaisuus. Esimerkin tapauksessa värit eivät mielestäni tuo lisäarvoa. Värimääritys color=’C0′ pakottaa pylväisiin käytössä olevan väripaletin ensimmäisen värin. Vastaavasti ’C1’ pakottaisi käytössä olevan väripaletin toisen värin jne.

Vierekkäset pylväät

Seuraavaksi luon dataframen, jossa on eri alueiden myynnit vuoden 2017 lisäksi myös vuodelta 2016 ja esitän molempien vuosien myynnit vierekkäisinä pylväinä:

raw_data={'Alue': ['Helsinki', 'Turku', 'Tampere', 'Oulu'], 
   'Myynti 2017': [1321847, 852669, 1032199, 568230],
   'Myynti 2016': [1203434, 923450, 1023563, 542399]}
myynnit2 = pd.DataFrame(raw_data)
myynnit2.index = myynnit2['Alue']
ax=myynnit2.plot.bar(figsize=(10,6), title='Myynti vuosina 
   2016 ja 2017', rot=0, width=0.7)
ax.set(xlabel='Alue', ylabel='Euroa')

kuviot4

Lisämääreenä määritin kuvion koon (figsize=(10,6)) ja käänsin luokka-akselin tekstit vaakaasentoon (rot=0).

Pinotut pylväät

Lisämääreellä stacked=True voin laatia pinotun pylväskaavion

ax=myynnit2.plot.bar(figsize=(10,6), title='Myynti 
   vuosina 2016 ja 2017', rot=0, width=0.7, legend=
   'reverse', stacked=True)
ax.set(xlabel='Alue', ylabel='Euroa')

kuviot5

Lisämääreellä legend=’reverse’ vaihdoin selitteen järjestyksen, jotta se vastaisi pinottujen pylväiden järjestystä.

Pinotut 100 % pylväät

Katsotaan vielä, miten laadin ristiintaulukoinnista 100 % pylväskuvion. Avaan datan, jossa on tietoja erään yrityksen työntekijöistä (muiden muassa sukupuoli ja koulutus) ja ristiintaulukoin koulutuksen ja sukupuolen. Kuvioksi sopii 100 % pinottu pylväskuvio:

df1 = pd.crosstab(df['koulutus'], df['sukupuoli'], margins = 
   True, normalize = 'columns')
df1.index = ['peruskoulu','2.aste','korkeakoulu',
   'ylempi korkeakoulu']
df1.columns = ['mies','nainen','yhteensä']

ax=df1[['mies','nainen']].transpose().plot.
   barh(stacked=True)
ax.set_xlabel('Prosenttia sukupuolesta')
ax.legend(loc='upper center', bbox_to_anchor=
   (0.5, 1.2), ncol=4)
vals = ax.get_xticks()
ax.set_xticklabels(['{:.0f} %'.format(x*100) 
   for x in vals])

kuviot6

Laadin ristiintaulukoinnin käyttämällä sukupuolta sarakemuuttujana (monilla on tapana ottaa selittävä muuttuja sarakemuuttujaksi). Tästä en kuitenkaan saa laadittua halutunlaista 100 % pylväskuviota ilman transpose()-toimintoa. Transpose() vaihtaa rivi ja sarakemuuttujat keskenään kuvion laadintaa varten.

Selitteen (legend) sijoittelukomento on taas melko esoteerisen näköinen. Pääset perille määreen bbox_to_anchor=(0.5, 1.2) tarkoituksesta kokeilemalla sulkeiden sisällä erilaisia lukuarvoja. Määre ncol=4 määrittää selitteen leveydeksi 4 saraketta (jokainen sarake sisältää yhden värin selitteen), joten värien selitykset sijoittuvat vierekkäin.

Figure-objekti

Plot-toiminnon myötä taustalla luodaan figure-objekti ja tämän sisälle axes-objekti. Voin tallentaa kuvion talletamalla figure-objektin:

plt.gcf().savefig('kuva.png')
plt.tight_layout()

gcf()-funktio palauttaa viimeksi luodun figure-objektin (get current figure). Tallennusformaatti määräytyy tiedostonimen tarkentimen (esim. png) perusteella. Matplotlib tukee yleisimpiä kuvaformaatteja.

plt.tight_layout() on tarpeen, jos tallennettu kuva ilman sitä näyttää reunoista liian ahtaalta.

Yhden figure-objektin sisälle on mahdollista luoda useita vierekkäin ja/tai allekkain sijoitettuja axes-objekteja. Yhden figure-objektin sisällä voi siis olla esimerkiksi useita pylväskuvioita.

Dataframe.plot

Tarkkaan ottaen hyödynsin tämän artikkelin kuvioiden luonnissa pandas-kirjaston dataframe.plot-toimintoa. Tämä toiminto kutsuu matplotlib.pyplot-kirjaston plot toimintoa. Lue lisää https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.plot.html

Lisää esimerkkejä pylväskuvioista löydät artikkelistani Pylväskaavioita Pythonilla.

Mainokset

2 vastausta artikkeliin “Kuviot Pythonilla 1”

Kommentit on suljettu.