Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: Matplotlib: Kaksi plottia samaan eri skaaloilla

Sivun loppuun

Jaska [15.03.2018 14:58:54]

#

Teen Pythonilla kuvaajien ja kaavioiden piirtämistä. Nyt tuli ongelma, johon en löytänyt ratkaisua. Minulla on kaksi datajoukkoa nollat ja selnollat. Ensimmäisestä pitäisi piirtää pylväsdiagrammi siten, että y-akselin skaalaus näkyisi vasemmalla puolella ja ulottuisi tietystä arvosta tiettyyn arvoon. Samaan kuvaajaan pitäisi saada myös viivadiagrammi, jonka skaala ulottuisi toisesta arvosta toiseen arvoon. Eli siis eri kuvaajien akselit näkyisivät kuten sivulla https://matplotlib.org/gallery/api/two_scales.html#sphx-glr-gallery-api-two-scales-py . Mutta miten tuon y-akselin skaalaus asetetaan kullekin plotille erikseen? Yritin käyttää funktiota set_ylim.

ax = plt.gca()
alanolla = min(nollat)
alayks = min(ykkoset)
ylanolla = max(nollat)
ylayks = max(ykkoset)

ax.set_ylim([0.9*min(alanolla, alayks), 1.1*max(ylanolla, ylayks)])
ax2 = ax.twinx()
ax2.set_ylim([0.9*min(selnollat), 1.1*max(selnollat)])
plt.plot(range(len(selnollat)), selnollat)
plt.bar(range(len(nollat)), nollat, color='C1')
plt.savefig('eka.png')

Muuttujissa on oikeat datat, mutta akselien skaalauksen säätäminen ei onnistunut. Tuo ax.set_ylim tuottaa pylväsdiagrammille oikean skaalan. Mutta toisen akselin skaalaa ax2 en saa näkyviin. Koodi piirtää kuvaajan, jossa pylväsdiagrammi on oikeassa skaalassa mutta sinisen viivan lukuarvoja ei näy kaaviosta. Kuitenkin muuttujassa selnollat on oikea datajoukko.

Grez [15.03.2018 21:31:25]

#

No sulta puuttuu tohon esimerkkiin verrattuna:

ax2.set_ylabel('otsikko', color=color)  # we already handled the x-label with ax1

Jaska [16.03.2018 10:47:47]

#

Ei vaikuttanut ongelmaan. Ilmeisesti set_ylabel vaan antaa akselille nimen. https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.set_ylabel.html

Grez [16.03.2018 11:34:22]

#

Jaa niin sun koodi käyttääkin ihan eri lähestymistapaa kuin toi esimerkki.

Näkisin, että sun koodissa ongelmana on, että määrittelet kahdet akselistot, mutta niiden määrittelyn jälkeen sanot vaan plotille yleisesti ettlä plt.plot ja plt.bar.

3. ja 2. viimeinen rivi pitäisi varmaan olla

ax2.plot(range(len(selnollat)), selnollat)
ax.bar(range(len(nollat)), nollat, color='C1')

Sit myös sellainen huomio, että jos datassasi sattuisi olemaan negatiivisia arvoja niin noi 0.9*min ja 1.1*max ei ihan toimi aiotulla tavalla.

Jaska [16.03.2018 12:08:29]

#

Grez kirjoitti:

3. ja 2. viimeinen rivi pitäisi varmaan olla

ax2.plot(range(len(selnollat)), selnollat)
ax.bar(range(len(nollat)), nollat, color='C1')

Kokeilin tuotakin, mutta se ei vaikuttanut piirrettyyn kuvaan.

Grez kirjoitti:

Sit myös sellainen huomio, että jos datassasi sattuisi olemaan negatiivisia arvoja niin noi 0.9*min ja 1.1*max ei ihan toimi aiotulla tavalla.

Totta, mutta tässä tapauksessa data on aina epänegatiivista.

Grez [16.03.2018 12:46:47]

#

Sitten lähtisin siitä että noissa sun salaisissa datoissa (nollat, ykkoset, selnollat) on jotain sellaista, joka aiheuttaa kuvitellun ongelmasi.

Siis ainakin ihan täydellisesti toimi mitä testasin itse keksimälläni datalla:

import numpy as np
import matplotlib.pyplot as plt

# Create some mock data
nollat = [1, 1.5, 2, 1.5, 1]
ykkoset = [2,3,2,4,3]
selnollat = [17,18,19,11,23]

ax = plt.gca()
alanolla = min(nollat)
alayks = min(ykkoset)
ylanolla = max(nollat)
ylayks = max(ykkoset)

ax.set_ylim(0.9*min(alanolla, alayks), 1.1*max(ylanolla, ylayks))
ax2 = ax.twinx()
ax2.set_ylim(0.9*min(selnollat), 1.1*max(selnollat))
ax.bar(range(len(nollat)), nollat, color='C1')
ax2.plot(range(len(selnollat)), selnollat)
plt.savefig('eka.png')

Tulos eka.png

Jaska [16.03.2018 13:23:06]

#

Okei. Nyt ongelma selvisi. Mulla oli jäänyt koodiin rivi

host = host_subplot(111, axes_class=AA.Axes)

Tämä aiheutti sen, että toinen akseli jäi piirtämättä. No, onneksi ohjelma toimii nyt.

Grez [16.03.2018 14:30:13]

#

Yleisesti ottaen jos laittaa minne tahansa muiden ihmeteltäväksi koodin, joka "ei toimi" niin kannattaa testata se vielä kerran ennen lähettämistä. Tässäkin tapauksessa olisit huomannut todellisen ongelman jo ennen lähettämistä.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta