2D-s ábrák

Legtöbbször a legjobb ábrák a legegyszerűbb ábrák! Az alábbiakban áttekintünk néhány egyszerű ábrakészítési módot, amelyek segíségével a leggyakrabban előforduló ábrázolási problémáinkat orvosolhatjuk. Fontos megjegyezni, hogy ábrát a matplotlib segítségével több hasonló módon is elő lehet állítani. Az alábbiakban törekedünk a lehető legegyszerűbb módszer bemutatására. Fontos azt is megjegyezni, hogy az alábbi példákban előforduló függvényopciók (kulcsszavas argumentumok) lehetséges értékeinek csak egy szűk halmazára térünk ki. A megfelelő paraméterek lehetséges értékei után vagy a matplotlib mintapáldái vagy a megfelelő függvények, pl. plot,hist,pcolor, contour és contourf docstring-jében érdemes kutatni!


In [1]:
#a már megszokott betöltési parancs
%pylab inline


Populating the interactive namespace from numpy and matplotlib

Egyszerű függvény és adat ábrázolás

Sok esetben a feladat egy ismert adathalmaz, netán egy analitikus függvény ábrázolása. Ha analitikus fügvénnyel van dolgunk, akkor az ábrázoláshoz először legyártunk kiértékelési pontokat, ezután ezekben a pontokban kiértékeljük az adott függvényt. Az alábbi példában a $\sin(x)$ függvényt fogjuk kiértékelni a $[-\pi,\pi]$ intervallumban 25 pontban.


In [2]:
x=linspace(-pi,pi,25);
y=sin(x);

Az ábrázolás (ahogy azt már korábban is láttuk) a plot paranccsal történik.


In [3]:
plot(x,y)


Out[3]:
[<matplotlib.lines.Line2D at 0x7fd8e836f128>]

Vizsgáljunk meg néhány kulcsszavas argumentumot, amely segítségével a plot parancs kimenetelét tudjuk változtatni. A color kulcsszó az ábrázolt adat színeit változtatja meg. Ez az ábra tartalmazza a matpotlib-ben néven nevezett színek nevét. Változtassuk meg a fenti ábrában a görbe színét pirosra!


In [4]:
plot(x,sin(x),color='red')


Out[4]:
[<matplotlib.lines.Line2D at 0x7fd8d8613860>]

A linewidth kulcsszó segítségével a vonalszélességen változtathatunk.


In [5]:
plot(x,sin(x),linewidth=3)


Out[5]:
[<matplotlib.lines.Line2D at 0x7fd8d8deaac8>]

A linestyle kulcscszó a vonalstílust állítja be. Ez lehet megnevezett kulcsszó (mint az alábbi példában) vagy szimbólum is.


In [6]:
plot(x,sin(x),linestyle='dashed') # szaggatott vonal (angolul: dashed line)


Out[6]:
[<matplotlib.lines.Line2D at 0x7fd8d68efda0>]

Ha üres stringet adunk vonalstílusnak, és a marker kulcsszót használjuk, akkor az ábrán csak pontok jelennek meg. Így például ábrázolhatunk olyan adatokat, amik nincsenek szépen sorbarendezve.


In [7]:
plot(x,sin(x),linestyle='',marker='o')


Out[7]:
[<matplotlib.lines.Line2D at 0x7fd8d8a08b38>]

Ha a linestyle és a marker kulcsszavakat egyszerre alkalmazzuk, akkor a markereket a kért vonalstílussal köti össze a matplotlib.


In [8]:
plot(x,sin(x),linestyle='dashed',marker='s')


Out[8]:
[<matplotlib.lines.Line2D at 0x7fd8d6be38d0>]

Természetesen ahogy már megszoktuk, kulcsszavas argumentumokból egyszerre többet is beadhatunk (vajon mit jelenthetnek azok a kulcsszók, amiről eddig nem volt szó?):


In [9]:
jellemzok=dict(color='green', linestyle='dashed', marker='o', markerfacecolor='blue',
               markeredgecolor='red',markeredgewidth=2, markersize=12 )

plot(x, sin(x), **jellemzok)


Out[9]:
[<matplotlib.lines.Line2D at 0x7fd8d85d1e48>]

Az ábra tengelyeinek tartományát az xlim(), illetve ylim() függvények segítségével tudjuk beállítani, melyeket a plot függvény után hívunk meg:


In [10]:
plot(x,sin(x))
xlim(-pi,pi);


A plot függvény számos más kulcsszavas argumentummal rendelkezik. A docstring-jében mindezek jól le vannak dokumentálva!


In [11]:
?plot

Ha két (vagy több) plot parancsot adunk ki egymás után, akkor az ábrán egyszerre két (vagy több) függvény is megjelenik.


In [12]:
plot(x,sin(x))
plot(x,cos(x))


Out[12]:
[<matplotlib.lines.Line2D at 0x7fd8d8059358>]

Speciális esete ennek az, amikor az egyik plot csak egyetlen pontot tartalmaz. Ezzel a módszerrel jelölhetünk érdekes pontokat a függvény görbéjén.


In [13]:
plot(x,sin(x))
plot(1,sin(1),'o')


Out[13]:
[<matplotlib.lines.Line2D at 0x7fd8d41c29b0>]

Ha több függvényt ábrázolunk, akkor a label kulcsszó és a legend() függvény segítségével tudjuk egyszerűen jelölni, hogy melyik görbe melyik függvényt ábrázolja.


In [14]:
plot(x,sin(x),label='sin(x)',color='red',linestyle='-',linewidth=3)
plot(x,cos(x),label='cos(x)',color='blue',linestyle='--',linewidth=3)
legend()


Out[14]:
<matplotlib.legend.Legend at 0x7fd8d40f6dd8>

Az xlabel() és az ylabel() függvények segítségével tengelyfeliratokat készíthetünk.


In [15]:
plot(x,sin(x))
xlabel(r'ido',fontsize=20)
ylabel('kiteres',fontsize=20)


Out[15]:
<matplotlib.text.Text at 0x7fd8d41d8c50>

Az xticks() és yticks() függvények a a tengelybeosztások formázásáért felelősek. Segítségükkel tudjuk a beosztásokat saját igényeink szerint beállítani. Ezen függvények dockstringjeit is érdemes megvizsgálni!


In [16]:
plot(x,sin(x))
xticks([-pi,-pi/2,0,pi/2,pi],[r'$-\pi$',r'$-\pi/2$',r'$0$',r'$\pi/2$',r'$\pi$'],fontsize=20);
yticks(linspace(-1,1,9)); 
#Vajon mi válltozott a fenti ábrához képest ?


Out[16]:
([<matplotlib.axis.YTick at 0x7fd8d409e358>,
  <matplotlib.axis.YTick at 0x7fd8d40bd710>,
  <matplotlib.axis.YTick at 0x7fd8d405d898>,
  <matplotlib.axis.YTick at 0x7fd8d4066470>,
  <matplotlib.axis.YTick at 0x7fd8d4066f60>,
  <matplotlib.axis.YTick at 0x7fd8d406a9b0>,
  <matplotlib.axis.YTick at 0x7fd8d40662e8>,
  <matplotlib.axis.YTick at 0x7fd8d406d588>,
  <matplotlib.axis.YTick at 0x7fd8d406df98>],
 <a list of 9 Text yticklabel objects>)

Végül nézzünk meg egy példát, amely a fent tanult trükköket egyszerre alkalmazva egy publikációs minőségű ábrát készít.


In [17]:
plot(x,sin(x),label='sin(x)',color='red',linestyle='-',linewidth=3)
plot(x,cos(x),label='cos(x)',color='blue',linestyle='--',linewidth=3)
xticks([-pi,-pi/2,0,pi/2,pi],[r'$-\pi$',r'$-\pi/2$',r'$0$',r'$\pi/2$',r'$\pi$'],fontsize=20);
yticks(linspace(-1,1,3),fontsize=20);
xlabel('ido',fontsize=20)
ylabel('kiteres',fontsize=20)
legend(loc='upper left',fontsize=20)
xlim(-pi,pi)
grid(True) #Vajon ez a függvény mit csinál ?


Fontos megjegyezni, hogy a vonal- és pontábrázolások kulcsszavas paraméterezését sok másik függvény is megörökölte. Így például 3D-s ábra készítésnél is hasonlóan használhatóak mint itt. Továbbá a tengelyfeliratozás és -beosztás kezelése is hasonlóan általánosabban használható, nem csak a plot() parancssal egyetemben!

Mérési adatok ábrázolása hibával-errorbar

Láttuk, hogy a plot függvény segítségével akár mérési adatpontokat is tudunk ábrázolni. Sokszor azonban a mérések során a mérési hiba is rendelkezésünkre áll! Vizsgáljunk meg erre egy példát! Az alábbiakban a történelmi napfoltadatok ábrázolásán keresztül igazi mérési adatokat fogunk ábrázolni. Az adatok a data könyvtárban található SN_m_tot_V2.0.txt file-ban vannak. Ahhoz hogy az adatok a rendelkezésünkre álljanak, először be kell tölteni a file tartalmát. Ezt legegyszerűbben a numpy modul loadtxt függvénye segítségével tehetjük meg. Ez a függvény egyszerűen strukturált adatfileokat olvas be egy array-be.


In [18]:
dat=loadtxt('data/SN_m_tot_V2.0.txt'); # a napfolt adatok betöltése.

A fenti parancs tehát a dat tömbbe beolvasta a file-ban található adatokat. A file 3. oszlopa tartalmazza a megfigyelés idejét években mérve, a 4. oszlop pedig a napfoltok számát. Ábrázoljuk az utolsó 100 pontot az adatfile-ból:


In [19]:
plot(dat[-100:,2],dat[-100:,3],linestyle='',marker='o')


Out[19]:
[<matplotlib.lines.Line2D at 0x7fd8d27529e8>]

Az 5. oszlop viszont a megfigyelések statisztikus hibáit tartalmazza. Ha a mérési pontokat és a hibát egy ábrán szeretnénk látni, akkor ezt az errorbar() függvény segítségével megtehetjük.


In [20]:
errorbar(dat[-100:,2],dat[-100:,3],dat[-100:,4],linestyle='',marker='o')


Out[20]:
<Container object of 3 artists>

Az errorbar() függvény tehát három bemenő oszlopot vár, amelyekből az első kettő a mérési pontok, illetve a mért értékek, a harmadik pedig a hiba. Ezeken felül, hasonlóan a plot()-hoz kulcsszavakkal vezérelhetjük a megjelenést. Az alábbi példa illusztrál néhány kulcsszót.


In [21]:
jellemzok=dict(linestyle='',marker='o',ecolor='green',capsize=4,capthick=2)
errorbar(dat[-100:,2],dat[-100:,3],dat[-100:,4],**jellemzok)


Out[21]:
<Container object of 3 artists>

További opciókról a docstringben kaphatunk némi felvilágosítást:


In [22]:
?errorbar

Természetesen két különféle ábrázolást is lehet egy képen megjeleníteni! Az alábbi példában egy plot() és egy errorbar() függvényt kombinálunk.


In [23]:
errorbar(dat[-300:,2],dat[-300:,3],dat[-300:,4],linestyle='',marker='o')
plot(dat[-300:,2],70*cos(2*pi/11*dat[-300:,2]-pi*0.25)+70,color='red',linewidth=3)


Out[23]:
[<matplotlib.lines.Line2D at 0x7fd8d3dd6a90>]

Hisztogramok

A hisztogramok a statisztikai elemzések fontos eszközei. A múlt órán már láttunk pár példát hisztogram készítésére a hist parancs segítségével. Ismerkedjünk most meg a hist() hisztogramgyártó-rutin néhány kulcsszavas argumentumával. Először is gyártsunk néhány véletlen számot!


In [24]:
meres1=randn(10000);
meres2=random.normal(2,0.5,10000);

Amint már korábban láttuk, ez a legegyszerűbb módja a hisztogramgyártásnak.


In [25]:
hist(meres1)


Out[25]:
(array([   20.,   150.,   731.,  2041.,  3065.,  2500.,  1169.,   278.,
           41.,     5.]),
 array([-3.72480582, -2.92629726, -2.12778869, -1.32928013, -0.53077157,
         0.267737  ,  1.06624556,  1.86475413,  2.66326269,  3.46177125,
         4.26027982]),
 <a list of 10 Patch objects>)

Ha növelni akarjuk a hisztogram felbontását, akkor azt a bins argumentummal tehetjük meg. Ha a bins egy számot kap a bemenetre, akkor annyi automatikusan legenerált beosztás szerint gyártódik le a hisztogramm.


In [26]:
hist(meres1,bins=100);


A beosztások széleit önkényesen is megadhatjuk!


In [27]:
hist(meres1,bins=[-2,0,1,2,3]);


Ha oszlopok helyett egy folytonos vonallal szeretnénk elkészíteni a hisztogramot, akkor a histtype kulcsszó segít!


In [28]:
hist(meres1,histtype='step');


Természetesen ahogy a plot parancsnál, úgy a hist parancsnál is lehet egyszerre több hisztogramot egy képen ábrázolni.


In [29]:
hist(meres1,bins=100,linewidth=0);
hist(meres2,bins=100,linewidth=0);


Ha nagyon eltakarná a két eloszlás egymást, akkor az alpha kulcsszó segítségével némileg áttetszővé tehetjük őket!


In [30]:
hist(meres1,bins=100,linewidth=0,alpha=0.5);
hist(meres2,bins=100,linewidth=0,alpha=0.5);


Kétváltozós függvények ábrázolásai, kontúrábrák, hőtérképek

Kétváltozós függvények megjelenítése az egy változósokéhoz hasonlóan, adatgyűjtéssel vagy mintavételezéssel kezdődik. A már ismert linspace() függvényt kombinálva a meshgrid() függvénnyel a múlt órán megismert módon mintavételezünk egy kétváltozós paraméterteret:


In [31]:
x2,y2 = meshgrid(linspace(-4,4,50),linspace(-3,3,50)) #mintavételezési pontok legyártása
z2 = sin(x2) ** 10 + cos(10 + y2 * x2) * cos(x2)          #függvény kiértékelés

A fenti kódsor tehát legyártott három tömböt. Az első kettő tartalmazza a (2 indexes array formájában) a mintavételezési pontok $x$ és $y$ koordinátáját. A z2 változó pedig a kiértékelt függvényt. Most már csak ábrázolni kell! Ezt legegyszerűbben - ahogy már láttuk - a pcolor() függvény teszi meg:


In [32]:
pcolor(x2,y2,z2)


Out[32]:
<matplotlib.collections.PolyCollection at 0x7fd8d3f1e898>

Hogy egy adott szín mit jelent, azt a colorbar() függvény segítségével tudhatjuk meg.


In [33]:
pcolor(x2,y2,z2)
colorbar()


Out[33]:
<matplotlib.colorbar.Colorbar at 0x7fd8d858d278>

Sok színsála létezik. Mindegyiknek megvan a maga előnye és hátránya. A matplotlib színskálák oldalán néhány megnevezett színsála közzül a cmap kulcsszó segítségével tudunk válogatni.


In [34]:
pcolor(x2,y2,z2,cmap='viridis')
colorbar()


Out[34]:
<matplotlib.colorbar.Colorbar at 0x7fd8d3646e48>

Kétváltozós függvényeket szokás kontúrok segítségével is ábrázolni. Egy kontúrvonal azokat a pontokat tartalmazza, ahol az adott két változós függvény ugyanazt az értéket veszi fel. A contour() függvény segítségével tudunk kontúrábrákat generálni:


In [35]:
contour(x2,y2,z2)


Out[35]:
<matplotlib.contour.QuadContourSet at 0x7fd8d3624a58>

Ha csak megadott kontúrértékekre vagyunk kíváncsiak, akkor azt a levels kulcsszó használatával tehetjük meg.


In [36]:
contour(x2,y2,z2,levels=[-0.5,0,0.5])


Out[36]:
<matplotlib.contour.QuadContourSet at 0x7fd8d36734e0>

A clabel() függvény segítségével a kontúr vonalakat a megfelelő értékek szerint tudjuk feliratozni.


In [37]:
cs=contour(x2,y2,z2,levels=[-0.5,0,0.5])
clabel(cs)


Out[37]:
<a list of 28 text.Text objects>

A contourf() függvény a pcolor() és a contour() függvények jó tulajdonságait ötvözi. Segítségével kitöltött szines ábrákat tudunk generálni, amelyek jobban illeszkednek a megjelenítendő függvény alakjához.


In [38]:
contourf(x2,y2,z2)


Out[38]:
<matplotlib.contour.QuadContourSet at 0x7fd8d3954d30>

A levels kulcsszó segítségével feljebb vehetjük a felbontást.


In [39]:
contourf(x2,y2,z2,levels=linspace(-1.5,1.5,100))
colorbar()


Out[39]:
<matplotlib.colorbar.Colorbar at 0x7fd8d3fbc978>

Előfordulhat, hogy a mintavételezés valamilyen oknál fogva nem volt egyenletes. Ekkor az adatpontok háromszögelésének segítségével lehet ábrázolni a kérdéses függvényt. Az alábbiakban erre látunk példát.

Gyártsunk le először is véletlenszerűen síkbeli pontokat!


In [40]:
tx,ty = [8*rand(50*50)-4,6*rand(50*50)-3]                 #mintavételezési pontok legyártása

Értékeljük ki ezekben a véletlen mintavételezési pontokban az ábrázolni kívánt függvényt!


In [41]:
tz = sin(tx) ** 10 + cos(10 + ty * tx) * cos(tx)          #függvény kiértékelés

Ha az adatpontok rendezetlenek, akkor a tripcolor(), tricontour() és tricontourf() függvényeket használhatjuk a pcolor(), contour(), illetve a contourf() függvényekkel teljesen analóg módon!


In [42]:
tripcolor(tx,ty,tz)


Out[42]:
<matplotlib.collections.PolyCollection at 0x7fd8d39c61d0>

In [43]:
tricontourf(tx,ty,tz,linspace(-1.5,1.5,100))


Out[43]:
<matplotlib.tri.tricontour.TriContourSet at 0x7fd8d344a278>

Vektorterek ábrázolási lehetőségei, nyílseregek és áramvonalak

A fizikában gyakran van dolgunk erőterekkel. Gondoljunk csak az elektrodinamikára vagy a meteorológiára. Vizsgáljuk meg az eddig ábrázolt kétváltozós függvény gradiensét. A síkbeli gradiensvektor az alábbiak szerint adódik:


In [44]:
u=-y2*sin(x2*y2 + 10)*cos(x2) + 10*sin(x2)**9*cos(x2) - sin(x2)*cos(x2*y2 + 10)
v=-x2*sin(x2*y2 + 10)*cos(x2)

A quiver() függvény segítségével a sík minden pontjához, amelyet az x2 és y2 tömbök definiálnak, egy az u és v tömbök által definiált vektort tudunk rendelni. Azaz a tér (x2[i],y2[i]) pontjába egy (u[i],v[i]) vektor kerül!


In [45]:
quiver(x2,y2,u,v)


Out[45]:
<matplotlib.quiver.Quiver at 0x7fd8d2ab8828>

Rajzoljuk csak minden harmadik vektort ki, piros színnel és kicsit vastagabban.


In [46]:
quiver(x2[::3, ::3], y2[::3, ::3], u[::3, ::3], v[::3, ::3],
    color='red',width=0.005)


Out[46]:
<matplotlib.quiver.Quiver at 0x7fd8d29c05c0>

Mint ahogy azt fent is említettük, további részletekért érdemes a dokumentációt böngészni!


In [47]:
?quiver

A quiver() alternatívája az áramvonal-ábrázolás, avagy a streamplot():


In [48]:
streamplot(x2[::3, ::3], y2[::3, ::3], u[::3, ::3], v[::3, ::3])


Out[48]:
<matplotlib.streamplot.StreamplotSet at 0x7fd8d171df28>

További részletek a dokumentációban:


In [49]:
?streamplot

A streamplot()-ot és a quiver()-t használhatjuk közösen a pcolor() és a kontúrkészítő rutinokkal!


In [50]:
pcolor(x2,y2,z2)
colorbar()
quiver(x2[::2,::2],y2[::2,::2],u[::2,::2],v[::2,::2],color='white',width=0.005)


Out[50]:
<matplotlib.quiver.Quiver at 0x7fd8d1620550>

In [51]:
contourf(x2,y2,z2,levels=linspace(-1.5,1.5,100))
colorbar()
streamplot(x2[::3, ::3], y2[::3, ::3], u[::3, ::3], v[::3, ::3],color='white')


Out[51]:
<matplotlib.streamplot.StreamplotSet at 0x7fd8d117efd0>

Ábrafeliratozás, nyilazás, ábratömbök

Egy ábra véglegesítése során sokszor előfordulhat, hogy valamilyen magyarázó szövegre van szükség, esetleg az ábra egy részét valamiért ki szeretnénk emelni. Ezt a text() és az annotate() függvények segítségével tehetjük meg. A text() függvény 3 alapvető bemenő paraméterrel rendelkezik. Az első kettő egy koordináta, a harmadik pedig egy string. Nézzünk egy példát!


In [52]:
plot(x,y);
text(1,0,'Ez egy felirat')
text(-3,0,'Ez egy másik felirat',fontsize=13,color='red')


Out[52]:
<matplotlib.text.Text at 0x7fd8d1154f28>

Ha egy részt ki szeretnénk emelni, akkor arra a legalkalmasabb megoldás az annotate(). Ezen függvény segítségével egy "rámutató" nyilat és egy magyarázó szöveget helyezhetünk el az ábrán. Az első bemenő paraméter egy string, ami a magyarázat, ezen kívül kulcsszavakkal vezéreljük a függvény további viselkedését. Az xy kulcsszó a kiemelni kívánt pont helye. Az xytext a magyarázat helye, az arrowprops pedig egy olyan dict-et tartalmaz, amely a nyíl tulajdonságait határozza meg.


In [53]:
plot(x,y)
annotate('lokális minimum', xy=(-pi/2, -1), xytext=(-pi, 0.5),arrowprops=dict(color='red',width=3),fontsize=20)


Out[53]:
<matplotlib.text.Annotation at 0x7fd8d1112240>

In [54]:
?annotate

Végül lássunk néhány példát ábratömbökre! A subplot() függvény segítségével tudunk ábratömböt vagy ábrarácsot generálni. Ha egy kódcellába több subplot() parancsot írunk, akkor minden subplot() parancs alatti ábrázolórutin külön alábrára kerül. A subplot(n,m,i) kód jelentése a következő: ami ezután jön, azt rajzold egy n*m-es ábratömb i-edik alábrájába. Vigyázzunk rá, hogy itt i nem haladhatja meg n*m-et!

Lássunk néhány példát:


In [55]:
figsize(12,4) #ábraméret nagyítása vízszintesen
subplot(1,2,1)
plot(x,y)
subplot(1,2,2)
pcolor(x2,y2,z2)


Out[55]:
<matplotlib.collections.PolyCollection at 0x7fd8d1005898>

In [56]:
figsize(6,8) #ábraméret nagyítása függőlegesen
subplot(2,1,1)
plot(x,y)
subplot(2,1,2)
pcolor(x2,y2,z2)


Out[56]:
<matplotlib.collections.PolyCollection at 0x7fd8d0eb1780>

Ábra mentése

A legenerált ábrákat a savefig() paranccsal tudjuk kimenteni képfile-okba.


In [57]:
figsize(6,4) # megszokott ábraméret visszaállítása
plot(x,y)
savefig('az_en_abram.png')