Kodėl matplotlib vis dar valdžia
Kai pradedi kalbėti apie duomenų vizualizaciją Python ekosistemoje, neišvengiamai grįžti prie matplotlib. Taip, yra Seaborn, Plotly, Bokeh ir daugybė kitų įrankių, bet matplotlib – tai tas senas patikimas draugas, kuris niekada neapvils. Biblioteka egzistuoja nuo 2003 metų, ir nors jos sintaksė kartais atrodo tarsi atkeliavusi iš MATLAB laikų (nes iš tiesų taip ir yra), ji suteikia tokį kontrolės lygį, kokio nerasite niekur kitur.
Kas įdomiausia – dauguma tų „modernesnių” vizualizacijos bibliotekų po gaubtu vis tiek naudoja matplotlib. Tai tarsi Linux branduolys duomenų vizualizacijos pasaulyje. Galbūt ne pats gražiausias, bet veikia kaip šveicariškas laikrodis ir leidžia padaryti absoliučiai viską.
Pradedantiesiems matplotlib gali pasirodyti bauginanti. Dokumentacija kartais primenanti labirintą, o Stack Overflow pilna skirtingų būdų pasiekti tą patį rezultatą. Bet kai supranti pagrindinę logiką, viskas susidėlioja į vietą.
Pirmieji žingsniai: pyplot prieš objektinį stilių
Vienas didžiausių matplotlib keblumų pradedantiesiems – tai du skirtingi būdai kurti grafikus. Yra pyplot interfeisas (paprastai importuojamas kaip plt), kuris atrodo papratesnis, ir objektinis požiūris su Figure bei Axes objektais.
Pyplot stilius atrodo taip:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.ylabel('Kvadratai')
plt.xlabel('Skaičiai')
plt.show()
Tai veikia puikiai interaktyviems Jupyter notebook’ams ar greitiems eksperimentams. Bet kai pradedi kurti sudėtingesnius grafikus ar nori daugiau kontrolės, objektinis stilius tampa būtinybe:
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4], [1, 4, 9, 16])
ax.set_ylabel('Kvadratai')
ax.set_xlabel('Skaičiai')
plt.show()
Skirtumas gali atrodyti minimalus, bet čia slypi esmė. Objektiniame stiliuje tu tiesiogiai valdai Figure (visą paveikslėlį) ir Axes (konkrečią grafiką) objektus. Tai leidžia kurti sudėtingas kompozicijas su keliais grafikais, tiksliai kontroliuoti kiekvieną elementą ir rašyti lankstesnį kodą.
Mano patarimas – nuo pat pradžių pratinkite prie objektinio stiliaus. Taip, reikės parašyti keletą papildomų simbolių, bet vėliau sutaupysite valandų besiblaškydami su pyplot keistybėmis.
Subplots architektūra: kaip išdėstyti kelis grafikus
Realybėje retai kada reikia vieno paprasto grafiko. Dažniausiai nori palyginti kelis duomenų rinkinius, parodyti skirtingas perspektyvas ar tiesiog efektyviai panaudoti ekrano plotą. Čia į žaidimą įsijungia subplots.
Paprasčiausias būdas sukurti kelis grafikus:
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
axes[0, 0].plot([1, 2, 3], [1, 4, 9])
axes[0, 1].scatter([1, 2, 3], [2, 3, 4])
axes[1, 0].bar([1, 2, 3], [3, 7, 5])
axes[1, 1].hist([1, 2, 2, 3, 3, 3, 4], bins=4)
plt.tight_layout()
plt.show()
Čia sukuriame 2×2 tinklelį grafikų. Parametras figsize nustato bendrą paveikslėlio dydį coliomis (taip, coliomis – dar vienas MATLAB palikimas). Funkcija tight_layout() automatiškai pakoreguoja tarpus tarp grafikų, kad jie nesiliestų.
Bet kas, jei nori nestandartinių išdėstymų? Pavyzdžiui, vienas didelis grafikas viršuje ir du mažesni apačioje? Čia praverčia GridSpec:
from matplotlib.gridspec import GridSpec
fig = plt.figure(figsize=(10, 8))
gs = GridSpec(3, 2, figure=fig)
ax1 = fig.add_subplot(gs[0:2, :]) # Užima pirmas dvi eilutes, abi stulpelius
ax2 = fig.add_subplot(gs[2, 0]) # Trečia eilutė, pirmas stulpelis
ax3 = fig.add_subplot(gs[2, 1]) # Trečia eilutė, antras stulpelis
GridSpec suteikia beveik neribotą lankstumą. Galite kurti sudėtingas dashboard’o tipo kompozicijas, kur kiekvienas grafikas užima tiksliai tiek vietos, kiek jums reikia.
Spalvos, stiliai ir estetika
Numatytieji matplotlib grafikai atrodo… na, pasakysiu tiesiai – atrodo kaip 2005 metų PowerPoint prezentacija. Bet tai nesunkiai pakeičiama.
Pirmiausia – spalvų schemos. Matplotlib turi integruotų spalvų paletių (colormaps), kurios tinka skirtingiems tikslams:
# Sekvencinės spalvos (skaičiams nuo mažo iki didelio)
plt.imshow(data, cmap='viridis')
# Diverguojančios spalvos (kai svarbu parodyti teigiamas/neigiamas reikšmes)
plt.imshow(data, cmap='RdBu')
# Kokybinės spalvos (kategoriniams duomenims)
plt.scatter(x, y, c=categories, cmap='Set3')
Viridis tapo numatytuoju pasirinkimu neatsitiktinai – ji perceptualiai vienoda (vienodi skirtumai duomenyse atrodo kaip vienodi skirtumai spalvose) ir gerai matoma žmonėms su spalvų aklumu.
Jei norite, kad jūsų grafikai atrodytų moderniau, naudokite stilius:
plt.style.use('seaborn-v0_8-darkgrid') # Seaborn stilius
# arba
plt.style.use('ggplot') # R ggplot2 stilius
# arba
plt.style.use('fivethirtyeight') # FiveThirtyEight naujienų portalo stilius
Galite net sukurti savo stilių, apibrėždami visus parametrus .mplstyle faile. Tai ypač naudinga, kai dirbate komandoje ir norite vienodo vizualinio identiteto.
Dar vienas patarimas – venkit pagundos naudoti per daug spalvų. Trys-keturios gerai parinktos spalvos beveik visada atrodo geriau nei vaivorykštė. Ir prašau, prašau, PRAŠAU – niekada nenaudokite 3D stulpelinių diagramų, nebent norite, kad duomenų analitikai verktu.
Anotacijos ir interaktyvumas
Geras grafikas pasakoja istoriją. Kartais tai istorija, kuriai reikia paaiškinimų. Anotacijos leidžia pabrėžti svarbius taškus, pridėti konteksto ar tiesiog padaryti grafiką suprantamesnį.
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(dates, values)
# Paprasta tekstinė anotacija
ax.text(important_date, important_value, 'Svarbus įvykis',
fontsize=12, ha='center')
# Anotacija su rodykle
ax.annotate('Čia kažkas įvyko',
xy=(event_date, event_value), # Taškas, į kurį rodome
xytext=(text_x, text_y), # Kur dedame tekstą
arrowprops=dict(arrowstyle='->', color='red', lw=2))
# Vertikali linija (pvz., žyminti datą)
ax.axvline(x=important_date, color='gray', linestyle='--', alpha=0.7)
Interaktyvumas – tai kita istorija. Standartinis matplotlib nėra interaktyvus, bet galite įjungti bazinį interaktyvumą:
%matplotlib widget # Jupyter notebook'e
# arba
plt.ion() # Įprastame Python skripte
Tai leidžia priartinti, nutolinti ir slinkti po grafiką. Jei reikia rimtesnio interaktyvumo (hover tooltips, dinaminiai filtrai ir pan.), geriau pereiti prie Plotly ar Bokeh. Bet paprastam duomenų tyrinėjimui matplotlib interaktyvumo pakanka.
Išsaugojimas ir eksportavimas
Sukūrėte tobulą grafiką – dabar reikia jį išsaugoti. Matplotlib palaiko daugybę formatų, bet ne visi jie sukurti vienodai.
# PNG – geras bendram naudojimui
plt.savefig('grafikas.png', dpi=300, bbox_inches='tight')
# PDF – idealus dokumentams ir publikacijoms
plt.savefig('grafikas.pdf', bbox_inches='tight')
# SVG – vektorinis formatas, idealus web'ui
plt.savefig('grafikas.svg', bbox_inches='tight')
Parametras dpi (dots per inch) kontroliuoja rastrinio vaizdo kokybę. 300 DPI yra standartas spaudai, 150 DPI pakanka ekranui. Parametras bbox_inches=’tight’ automatiškai apkerpa tuščią plotą aplink grafiką.
Svarbus niuansas – jei saugote daug grafikų cikle, nepamirškite uždaryti figūrų:
for i in range(100):
fig, ax = plt.subplots()
# ... kuriate grafiką ...
plt.savefig(f'grafikas_{i}.png')
plt.close(fig) # SVARBU! Kitaip užkimšite atmintį
Be plt.close() atmintis greitai prisipildys, nes matplotlib saugo visas sukurtas figūras. Tai klasikinė klaida, dėl kurios skriptai pradeda lėtėti ar net užstringa.
Dažniausios klaidos ir kaip jų išvengti
Per metus dirbant su matplotlib, susiduri su tomis pačiomis problemomis vėl ir vėl. Štai keletas, kurias verta žinoti iš anksto.
**Problema: Grafikas neatsiranda**
Dažniausiai tai reiškia, kad pamiršote plt.show(). Jupyter notebook’uose tai ne problema (grafikai rodomi automatiškai), bet įprastuose Python skriptuose būtina.
**Problema: Keisti spalvas ar stilius neveikia**
Tikriausiai keičiate parametrus po to, kai jau nupiešėte grafiką. Matplotlib dažniausiai reikia nustatyti parametrus PRIEŠ piešiant:
# Blogai
ax.plot(x, y)
ax.set_color('red') # Per vėlu!
# Gerai
ax.plot(x, y, color='red')
**Problema: Legendos uždengia duomenis**
Legendos poziciją galite kontroliuoti:
ax.legend(loc='best') # Automatiškai randa geriausią vietą
# arba
ax.legend(loc='upper left', bbox_to_anchor=(1, 1)) # Už grafiko ribų
**Problema: Datos X ašyje susigrūdusios ir nesuprantamos**
Naudokite date formatavimą ir pasukite etiketes:
import matplotlib.dates as mdates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
Kai matplotlib tampa per daug: alternatyvos ir papildymai
Būkime sąžiningi – matplotlib nėra idealus visiems scenarijams. Jei kuriate interaktyvius dashboard’us, Plotly ar Dash bus geresnis pasirinkimas. Jei reikia greitai sukurti gražius statistinius grafikus, Seaborn sutaupo laiko. Jei dirbate su geografiniais duomenimis, Folium ar Plotly Express bus efektyvesni.
Bet štai kas įdomu – visos šios bibliotekos gali dirbti kartu su matplotlib. Seaborn iš esmės yra matplotlib wrapper’is su protingesniais numatytaisiais nustatymais. Pandas plot() funkcijos po gaubtu naudoja matplotlib. Net Plotly gali eksportuoti į matplotlib formatą.
Tai reiškia, kad laikas, investuotas į matplotlib mokymąsi, niekada nenueis veltui. Tai fundamentas, ant kurio stovi didelė dalis Python vizualizacijos ekosistemos.
Praktinis patarimas – pradėkite su Seaborn paprastiems statistiniams grafikams, bet žinokite, kaip nukopijuoti į matplotlib lygį, kai reikia detalesnės kontrolės:
import seaborn as sns
# Seaborn sukuria gražų grafiką
ax = sns.scatterplot(data=df, x='x', y='y', hue='category')
# Bet dabar galite jį modifikuoti su matplotlib
ax.set_title('Mano pavadinimas', fontsize=16, fontweight='bold')
ax.axhline(y=threshold, color='red', linestyle='--')
Kur tobulėti toliau ir kaip visa tai sujungti
Matplotlib – tai įrankis, kurį išmoksti darydamas. Galite perskaityti visą dokumentaciją (nors nerekomenduoju, nebent turite labai daug laiko), bet tikrasis mokymasis vyksta sprendžiant realias problemas.
Geriausi šaltiniai tobulinimui: oficiali matplotlib galerija (matplotlib.org/stable/gallery) – čia rasite šimtus pavyzdžių su pilnu kodu. Kai reikia konkretaus grafiko tipo, pradėkite nuo čia. Stack Overflow, žinoma, bet būkite atsargūs – daug senų atsakymų naudoja pasenusią sintaksę. Python Graph Gallery (python-graph-gallery.com) – puiki inspiracija ir praktiniai pavyzdžiai.
Dar vienas patarimas – sukurkite sau šabloną su dažniausiai naudojamais nustatymais. Mano atrodo maždaug taip:
def setup_plot(figsize=(10, 6)):
fig, ax = plt.subplots(figsize=figsize)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.grid(True, alpha=0.3)
return fig, ax
# Naudojimas
fig, ax = setup_plot()
ax.plot(x, y)
Tai sutaupo laiko ir užtikrina vienodą stilių visuose grafikuose.
Galiausiai, nepamirškite, kad vizualizacija – tai komunikacijos įrankis. Geriausias grafikas nėra tas, kuris naudoja visas matplotlib galimybes, o tas, kuris aiškiausiai perteikia jūsų žinutę. Kartais paprastas linijinis grafikas su gerai parinktu pavadinimu veikia geriau nei sudėtinga 3D vizualizacija su animacijomis.
Matplotlib suteikia jums galią kurti bet kokią vizualizaciją, kokią tik galite įsivaizduoti. Bet su didele galia ateina ir didelė atsakomybė – atsakomybė nekurti baisių grafikų. Naudokite šią galią išmintingai, ir jūsų duomenys papasakos įtikinamą istoriją.
