Permalänk
Medlem

python och matplotlib

har ett litet problem med att min kod inte låter mig ha en enstaka graf, utan måste ha två - förstår inte varför.

någon som kan hjälpa mig med detta?
(är inte en skoluppgift eller dylikt, gör detta för att det är roligt)

import matplotlib.pyplot as plt import yfinance as yf from matplotlib.animation import FuncAnimation # dont change this tickers = [] def update_graphs(_): for idx, ticker in enumerate(tickers): stock = yf.Ticker(ticker) history = stock.history(period="1d", interval="1m") datetime = history.index closing = history['Close'] opening = history['Open'] high = history['High'] low = history['Low'] volume = history['Volume'] axes[idx].clear() axes[idx].plot(closing, label="Close", color="green") axes[idx].plot(opening, label="Open", color="blue") axes[idx].fill_between(datetime, low, high, color="orange", alpha=0.3, label="High-Low Range") axes[idx].set_title(f"{ticker} : Close: {closing.iloc[-1]:.2f} SEK") axes[idx].set_xlabel("T") axes[idx].set_ylabel("Price") axes[idx].grid() ax2 = axes[idx].twinx() ax2.bar(datetime, volume, color="grey", alpha=0.5, label="Volume", width=0.02) ax2.set_ylabel("Volume") if __name__ == "__main__": tickers = input("Enter ticker symbols separated by commas: ").split(",") tickers = [ticker.strip() for ticker in tickers] fig, axes = plt.subplots((len(tickers)), 1) ani = FuncAnimation(fig, update_graphs, interval=60000, cache_frame_data=False) plt.tight_layout() plt.show()

Permalänk
Medlem

Jag förstår inte riktigt, kan du visa bild med hur du vill ha det? Du skapar en bar plot och en vanlig plot vad jag kan se?

Permalänk
Medlem
Skrivet av pine-orange:

Jag förstår inte riktigt, kan du visa bild med hur du vill ha det? Du skapar en bar plot och en vanlig plot vad jag kan se?

förlåt jag var otydlig

när programmet startar så blir man ombedd att mata in de symboler/tickers/aktier man vill ha som den sedan bearbetar genom att splittra alla symboler var för sig och sedan tar bort alla blanksteg. därefter så skapar den grafer baserad på hur många symboler eller aktier man matat in.

# mata in aktier och splittra alla efter komma tecken tickers = input("Enter ticker symbols separated by commas: ").split(",") # ta bort alla blanksteg och dylikt tickers = [ticker.strip() for ticker in tickers] # skapa en plot/subplot med antalet "längden av tickers" x 1 fig, axes = plt.subplots((len(tickers)), 1)

nu när jag sovit lite tror jag att jag bör göra en if-statement och ifall len(tickers) är likamed 1 så ska den kanske inte göra en subplot utan en vanlig plot. det kanske fungerar?

edit: nu när jag vaknat så tror jag om jag gör min if statement så kommer det bara bli massa överdriven extra kod, måste finnas ett enklare sätt att göra.

edit 2: går att fuska lite och bara lägga ett "," komma efter enstaka aktie och då fungerar programmet, så det är definitivt subplot funktionen som bråkar

felkod när jag kör med endast 1 aktie:

### här kör jag med "IPCO.ST," notera "," kommatecken PS D:\Py> & "C:/Program Files/Python313/python.exe" d:/Py/aktier4.py Enter ticker symbols separated by commas: IPCO.ST, Traceback (most recent call last): File "C:\Program Files\Python313\Lib\site-packages\matplotlib\cbook.py", line 361, in process func(*args, **kwargs) ~~~~^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\site-packages\matplotlib\animation.py", line 928, in _start self._init_draw() ~~~~~~~~~~~~~~~^^ File "C:\Program Files\Python313\Lib\site-packages\matplotlib\animation.py", line 1770, in _init_draw self._draw_frame(frame_data) ~~~~~~~~~~~~~~~~^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\site-packages\matplotlib\animation.py", line 1789, in _draw_frame self._drawn_artists = self._func(framedata, *self._args) ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^ File "d:\Py\aktier4.py", line 15, in update_graphs stock = yf.Ticker(ticker) File "C:\Program Files\Python313\Lib\site-packages\yfinance\ticker.py", line 35, in __init__ super(Ticker, self).__init__(ticker, session=session, proxy=proxy) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\site-packages\yfinance\base.py", line 65, in __init__ raise ValueError("Empty ticker name") ValueError: Empty ticker name PS D:\Py> & "C:/Program Files/Python313/python.exe" d:/Py/aktier4.py ### här kör jag med "IPCO.ST" notera utan "," kommatecken Enter ticker symbols separated by commas: IPCO.ST Traceback (most recent call last): File "C:\Program Files\Python313\Lib\site-packages\matplotlib\cbook.py", line 361, in process func(*args, **kwargs) ~~~~^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\site-packages\matplotlib\animation.py", line 928, in _start self._init_draw() ~~~~~~~~~~~~~~~^^ File "C:\Program Files\Python313\Lib\site-packages\matplotlib\animation.py", line 1770, in _init_draw self._draw_frame(frame_data) ~~~~~~~~~~~~~~~~^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\site-packages\matplotlib\animation.py", line 1789, in _draw_frame self._drawn_artists = self._func(framedata, *self._args) ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^ File "d:\Py\aktier4.py", line 25, in update_graphs axes[idx].clear() ~~~~^^^^^ TypeError: 'Axes' object is not subscriptable

bild 1 aktie "IPCO.ST":

bild med komma tricket "IPCO.ST," - X är vad jag vill bli av med:

min fråga är väl nu egentligen om det går att fixa utan att göra en helt ny plot för när det blir en enstaka aktie?

Permalänk
Medlem

borde något sånthär fungera?

if len(tickers) == 1: fig, axes = plt.plot() else: fig, axes = plt.subplots((len(tickers)), 1)

Permalänk
Medlem
Skrivet av Vetulus:

borde något sånthär fungera?

if len(tickers) == 1: fig, axes = plt.plot() else: fig, axes = plt.subplots((len(tickers)), 1)

Jag tror inte det kommer fungera. Problemet uppstår tidigare än så, matplotlib tillåter dig inte att subscripta axes som bara har ett element om jag minns rätt. Du kan inte skriva axes[0] för bara ett element, det fungerar endast om du har två eller fler.

Ett alternativ är att du kör axes[index du inte vill ha].set_axis_off() då försvinner den tomma grafen men då blir det bara helt tomt istället.

Permalänk
Medlem

Börjar med en sak jag såg då jag skriver från mobilen.
Varje gång du kör

tickers = [] tickers = nånting

Så blir "tickers" omgjord till vad nånting är, det är alltså inte en lista längre som när du initierade den.
Det du istället vill göra är

tickers = [] tickers.append(nånting)

Nu lägger du till ett eller flera värden i din lista.

Permalänk
Medlem
Skrivet av pine-orange:

Jag tror inte det kommer fungera. Problemet uppstår tidigare än så, matplotlib tillåter dig inte att subscripta axes som bara har ett element om jag minns rätt. Du kan inte skriva axes[0] för bara ett element, det fungerar endast om du har två eller fler.

Ett alternativ är att du kör axes[index du inte vill ha].set_axis_off() då försvinner den tomma grafen men då blir det bara helt tomt istället.

Jag antar att jag får göra två separata funktioner då, typ def update_singlegraph och def update_graphs som jag har nu, en för när det blir bara en graf och en till för när det blir flera? tänker jag rätt nu för att få det att bolla så bra som möjligt?

Skrivet av swesen:

Börjar med en sak jag såg då jag skriver från mobilen.
Varje gång du kör

tickers = [] tickers = nånting

Så blir "tickers" omgjord till vad nånting är, det är alltså inte en lista längre som när du initierade den.
Det du istället vill göra är

tickers = [] tickers.append(nånting)

Nu lägger du till ett eller flera värden i din lista.

Blir lite förvirrad nu men det står att type är list när jag printar ut type, menar du att "tickers = input......" blir en sträng och sedan omvandlas till en lista när jag använder split? blir ju en lista tillslut ändå, det borde väl inte vara något problem?

tickers = input("Enter ticker symbols separated by commas: ").split(",") tickers = [ticker.strip() for ticker in tickers] print(type(tickers)) terminal output: <class 'list'>

Permalänk
Medlem
Skrivet av Vetulus:

Jag antar att jag får göra två separata funktioner då, typ def update_singlegraph och def update_graphs som jag har nu, en för när det blir bara en graf och en till för när det blir flera? tänker jag rätt nu för att få det att bolla så bra som möjligt?

Du skulle kunna göra något sånt här också. När du stänger av axis[1] så justerar du positionen och storlek på den ena grafen så att den hamnar mer i mitten.

import matplotlib.pyplot as plt import numpy as np # Some example data to display x = np.linspace(0, 2 * np.pi, 400) y = np.sin(x ** 2) fig, axs = plt.subplots(2) fig.suptitle('Vertically stacked subplots') axs[0].plot(x, y) axs[1].set_axis_off() left = 0.125 bottom = 0.2 width = 0.8 height = 0.6 axs[0].set_position([left, bottom, width, height]) plt.show()

Permalänk
Medlem
Skrivet av pine-orange:

Du skulle kunna göra något sånt här också. När du stänger av axis[1] så justerar du positionen och storlek på den ena grafen så att den hamnar mer i mitten.

import matplotlib.pyplot as plt import numpy as np # Some example data to display x = np.linspace(0, 2 * np.pi, 400) y = np.sin(x ** 2) fig, axs = plt.subplots(2) fig.suptitle('Vertically stacked subplots') axs[0].plot(x, y) axs[1].set_axis_off() left = 0.125 bottom = 0.2 width = 0.8 height = 0.6 axs[0].set_position([left, bottom, width, height]) plt.show()

men om detta fungerar, så kommer problemet med att mata in aktier vara kvar fortfarande, hur löser jag det?

Just nu måste jag skriva "IPCO.ST," - notera komma tecknet - istället för "IPCO.ST" - notera avsaknaden av kommatecknet. Är säkert något jätte enkelt men vet inte vad jag ska googla på för att få en lösning.

Permalänk
Medlem
Skrivet av Vetulus:

men om detta fungerar, så kommer problemet med att mata in aktier vara kvar fortfarande, hur löser jag det?

Just nu måste jag skriva "IPCO.ST," - notera komma tecknet - istället för "IPCO.ST" - notera avsaknaden av kommatecknet. Är säkert något jätte enkelt men vet inte vad jag ska googla på för att få en lösning.

Beroende på användningsområde kanske du vill göra någon form av validering som testar om det är en ticker som finns osv, men enklast är att göra något sånt här tror jag:

tickers = [] while True: ticker = input("Enter a ticker: ") if ticker == "stop": break else: tickers.append(ticker) print(tickers)

Du skriver din ticker och sen enter, det fortsätter tills du skriver stop.

Permalänk
Medlem
Skrivet av pine-orange:

Beroende på användningsområde kanske du vill göra någon form av validering som testar om det är en ticker som finns osv, men enklast är att göra något sånt här tror jag:

tickers = [] while True: ticker = input("Enter a ticker: ") if ticker == "stop": break else: tickers.append(ticker) print(tickers)

Du skriver din ticker och sen enter, det fortsätter tills du skriver stop.

Ska prova allt och återkommer under dagen! tack för hjälpen!

Permalänk
Medlem
Skrivet av Vetulus:

Blir lite förvirrad nu men det står att type är list när jag printar ut type, menar du att "tickers = input......" blir en sträng och sedan omvandlas till en lista när jag använder split? blir ju en lista tillslut ändå, det borde väl inte vara något problem?

tickers = input("Enter ticker symbols separated by commas: ").split(",") tickers = [ticker.strip() for ticker in tickers] print(type(tickers)) terminal output: <class 'list'>

Ser nu att det riktiga problemet är att du inte tar bort den tomma strängen ifrån listan.

# Om input = "IPCO.ST," tickers = input("Enter ticker symbols separated by commas: ").split(",") # nu blir tickers tilldelad ["IPCO.ST", ""] tickers = [ticker.strip() for ticker in tickers] # nu blir tickers tilldelad ["IPCO.ST", ""] igen då .strip() bara tar bort whitespace len(tickers) # är fortfarande 2 # lägger du till filter efter strip så bör du inte få en tom "axes" tickers = list(filter(None, tickers)) len(tickers) # = 1

Permalänk

import matplotlib.pyplot as plt import yfinance as yf from matplotlib.animation import FuncAnimation import sys # Importerar sys för att kunna avsluta programmet snyggt om inga giltiga tickers matas in # Denna lista kommer att fyllas med tickers efter användarens input tickers = [] def update_graphs(_): """ Hämtar den senaste minutdatan för varje ticker och uppdaterar motsvarande subplot. Kallas av FuncAnimation. """ # 'axes' garanteras nu vara en itererbar sekvens (lista eller numpy array) # oavsett om det finns en eller flera tickers. for idx, ticker in enumerate(tickers): # Kontrollerar om idx är inom gränserna för 'axes'. # Denna kontroll är mest för säkerhet; loopens storlek bör matcha antalet subplots. if idx >= len(axes): print(f"Varning: Index {idx} utanför gränserna för 'axes' med längd {len(axes)}") continue # Hoppa över om något oväntat skulle hända stock = yf.Ticker(ticker) # Hämtar historik för senaste dagen med 1-minutsintervall history = stock.history(period="1d", interval="1m") # Kontrollera om data kunde hämtas. Om inte, hantera tom graf. if history.empty: print(f"Varning: Kunde inte hämta data för {ticker}. Hoppar över.") # Rensa den subplot som skulle ha använts axes[idx].clear() axes[idx].set_title(f"{ticker}: Ingen data tillgänglig") axes[idx].grid(False) # Stäng av rutnätet för en tom graf # Kontrollera om twinx-axeln skapades innan vi rensar (för att undvika fel om den inte finns) # Notera: Det här hanterar inte fallet där twinx-axeln redan fanns och rensades. # För en tom graf räcker det oftast att bara rensa huvudaxeln och titeln. # Den sekundära axeln skapas ändå inte om datan är tom. continue # Gå till nästa ticker i loopen datetime_index = history.index # Bytte namn från 'datetime' för att undvika kollision med inbyggt namn closing = history['Close'] opening = history['Open'] high = history['High'] low = history['Low'] volume = history['Volume'] # Vi har nu säkerställt att 'axes' är en itererbar sekvens, # så axes[idx] kommer att ge rätt Axes-objekt. current_ax = axes[idx] current_ax.clear() # Rensa den befintliga grafen innan ny data ritas # Rita de olika dataserierna current_ax.plot(datetime_index, closing, label="Stängningskurs", color="green") current_ax.plot(datetime_index, opening, label="Öppningskurs", color="blue") current_ax.fill_between(datetime_index, low, high, color="orange", alpha=0.3, label="Högsta-Lägsta intervall") current_ax.set_title(f"{ticker} : Stängning: {closing.iloc[-1]:.2f} SEK") # Uppdatera titeln med senaste stängningskurs current_ax.set_xlabel("Tid") current_ax.set_ylabel("Pris (SEK)") current_ax.grid(True) # Se till att rutnätet är på # Skapa en sekundär y-axel för volymen ax2 = current_ax.twinx() ax2.bar(datetime_index, volume, color="grey", alpha=0.5, label="Volym", width=0.02) ax2.set_ylabel("Volym") # Lägg till legender (det kan bli lite rörigt med twinx, kan behöva samla handles och labels) # För enkelhetens skull lägger vi huvudlegenden på den primära axeln. # en kombinerad legend kan göras utanför loopen efter att alla axlar är ritade. # current_ax.legend(loc='upper left') # ax2.legend(loc='upper right') # Kan överlappa if __name__ == "__main__": # Här skrivs den globala 'tickers'-listan över, vilket är okej i det här fallet. input_string = input("Mata in tickersymboler separerade med kommatecken: ") tickers = input_string.split(",") # Ta bort blanksteg före och efter varje ticker tickers = [ticker.strip() for ticker in tickers] # Filtrera bort eventuella tomma strängar som kan finnas kvar # t.ex. från extra kommatecken (som i "AAPL,,MSFT" eller "IPCO.ST,") tickers = list(filter(None, tickers)) # Kontrollera om det finns några tickers kvar efter filtreringen if not tickers: print("Inga giltiga tickersymboler angavs. Avslutar.") sys.exit() # Avsluta programmet # Skapa subplots baserat på antalet tickers. # Hantera fallet med en enda ticker specifikt för att säkerställa att 'axes' # alltid är en itererbar sekvens (lista eller numpy array) för att loopen ska fungera. if len(tickers) == 1: # plt.subplots(1, 1) returnerar en figur och ett enda Axes-objekt. fig, axes_obj = plt.subplots(1, 1) # Vi omsluter det enda Axes-objektet i en lista så att loopen alltid kan använda axes[idx]. axes = [axes_obj] else: # För flera tickers returnerar plt.subplots en figur och en numpy array av Axes-objekt. # Vi använder squeeze=False för att säkerställa att 'axes' alltid är en 2D-array # även om det bara är en kolumn (len(tickers), 1). Därefter plattar vi till den. fig, axes = plt.subplots(len(tickers), 1, squeeze=False) # Plattar till numpy-arrayen till en 1D-array för enklare indexering (axes[idx]) axes = axes.flatten() # Skapa animationen. 'update_graphs' kallas med intervallet 60000 ms (1 minut). # cache_frame_data=False är bra när du hämtar ny realtidsdata varje gång. ani = FuncAnimation(fig, update_graphs, interval=60000, cache_frame_data=False) # Justera layouten för att förhindra att titlar och etiketter överlappar varandra plt.tight_layout() # Visa plotten plt.show()

ville att jag skulle skriva in taggar för [.code][/.code]
Permalänk
Medlem
Skrivet av sweanisse:

detta borde nog fungera bättre

import matplotlib.pyplot as plt
import yfinance as yf
from matplotlib.animation import FuncAnimation
import sys # Importerar sys för att kunna avsluta programmet snyggt om inga giltiga tickers matas in

# Denna lista kommer att fyllas med tickers efter användarens input
tickers = []

def update_graphs(_):
"""
Hämtar den senaste minutdatan för varje ticker och uppdaterar motsvarande subplot.
Kallas av FuncAnimation.
"""
# 'axes' garanteras nu vara en itererbar sekvens (lista eller numpy array)
# oavsett om det finns en eller flera tickers.
for idx, ticker in enumerate(tickers):
# Kontrollerar om idx är inom gränserna för 'axes'.
# Denna kontroll är mest för säkerhet; loopens storlek bör matcha antalet subplots.
if idx >= len(axes):
print(f"Varning: Index {idx} utanför gränserna för 'axes' med längd {len(axes)}")
continue # Hoppa över om något oväntat skulle hända

stock = yf.Ticker(ticker)
# Hämtar historik för senaste dagen med 1-minutsintervall
history = stock.history(period="1d", interval="1m")

# Kontrollera om data kunde hämtas. Om inte, hantera tom graf.
if history.empty:
print(f"Varning: Kunde inte hämta data för {ticker}. Hoppar över.")
# Rensa den subplot som skulle ha använts
axes[idx].clear()
axes[idx].set_title(f"{ticker}: Ingen data tillgänglig")
axes[idx].grid(False) # Stäng av rutnätet för en tom graf
# Kontrollera om twinx-axeln skapades innan vi rensar (för att undvika fel om den inte finns)
if hasattr(axes[idx], 'right_ax'):
axes[idx].right_ax.clear()
continue # Gå till nästa ticker i loopen

datetime_index = history.index # Bytte namn från 'datetime' för att undvika kollision med inbyggt namn
closing = history['Close']
opening = history['Open']
high = history['High']
low = history['Low']
volume = history['Volume']

# Vi har nu säkerställt att 'axes' är en itererbar sekvens,
# så axes[idx] kommer att ge rätt Axes-objekt.
current_ax = axes[idx]

current_ax.clear() # Rensa den befintliga grafen innan ny data ritas

# Rita de olika dataserierna
current_ax.plot(datetime_index, closing, label="Stängningskurs", color="green")
current_ax.plot(datetime_index, opening, label="Öppningskurs", color="blue")
current_ax.fill_between(datetime_index, low, high, color="orange", alpha=0.3, label="Högsta-Lägsta intervall")
current_ax.set_title(f"{ticker} : Stängning: {closing.iloc[-1]:.2f} SEK") # Uppdatera titeln med senaste stängningskurs
current_ax.set_xlabel("Tid")
current_ax.set_ylabel("Pris (SEK)")
current_ax.grid(True) # Se till att rutnätet är på

# Skapa en sekundär y-axel för volymen
ax2 = current_ax.twinx()
ax2.bar(datetime_index, volume, color="grey", alpha=0.5, label="Volym", width=0.02)
ax2.set_ylabel("Volym")

# Lägg till legender (det kan bli lite rörigt med twinx, kan behöva samla handles och labels)
# För enkelhetens skull lägger vi huvudlegenden på den primära axeln.
# en kombinerad legend kan göras utanför loopen efter att alla axlar är ritade.
# current_ax.legend(loc='upper left')
# ax2.legend(loc='upper right') # Kan överlappa

if __name__ == "__main__":
# Här skrivs den globala 'tickers'-listan över, vilket är okej i det här fallet.
input_string = input("Mata in tickersymboler separerade med kommatecken: ")
tickers = input_string.split(",")
# Ta bort blanksteg före och efter varje ticker
tickers = [ticker.strip() for ticker in tickers]
# Filtrera bort eventuella tomma strängar som kan finnas kvar
# t.ex. från extra kommatecken (som i "AAPL,,MSFT" eller "IPCO.ST,")
tickers = list(filter(None, tickers))

# Kontrollera om det finns några tickers kvar efter filtreringen
if not tickers:
print("Inga giltiga tickersymboler angavs. Avslutar.")
sys.exit() # Avsluta programmet

# Skapa subplots baserat på antalet tickers.
# Hantera fallet med en enda ticker specifikt för att säkerställa att 'axes'
# alltid är en itererbar sekvens (lista eller numpy array) för att loopen ska fungera.
if len(tickers) == 1:
# plt.subplots(1, 1) returnerar en figur och ett enda Axes-objekt.
fig, axes_obj = plt.subplots(1, 1)
# Vi omsluter det enda Axes-objektet i en lista så att loopen alltid kan använda axes[idx].
axes = [axes_obj]
else:
# För flera tickers returnerar plt.subplots en figur och en numpy array av Axes-objekt.
# Vi använder squeeze=False för att säkerställa att 'axes' alltid är en 2D-array
# även om det bara är en kolumn (len(tickers), 1). Därefter plattar vi till den.
fig, axes = plt.subplots(len(tickers), 1, squeeze=False)
# Plattar till numpy-arrayen till en 1D-array för enklare indexering (axes[idx])
axes = axes.flatten()

# Skapa animationen. 'update_graphs' kallas med intervallet 60000 ms (1 minut).
# cache_frame_data=False är bra när du hämtar ny realtidsdata varje gång.
ani = FuncAnimation(fig, update_graphs, interval=60000, cache_frame_data=False)

# Justera layouten för att förhindra att titlar och etiketter överlappar varandra
plt.tight_layout()

# Visa plotten
plt.show()

koden blev väldigt svår att läsa, skulle du kunna lägga den innanför kod taggen "[.code]" utan prick och avsluta den med "[/code.]" utan prick? sitter och försöker ge allt rätt indentation men det är svårt på min lilla laptop

edit: fixade formateringen på den nu men jag vet inte om det är att jag som inte fixat indentationen på korrekt sätt eller om det är koden men jag får bara en tom graf med din kod däremot funkade det att bara ange en enda aktie/symbol/ticker etc utan att det pep

Permalänk
Medlem
Skrivet av swesen:

Ser nu att det riktiga problemet är att du inte tar bort den tomma strängen ifrån listan.

# Om input = "IPCO.ST," tickers = input("Enter ticker symbols separated by commas: ").split(",") # nu blir tickers tilldelad ["IPCO.ST", ""] tickers = [ticker.strip() for ticker in tickers] # nu blir tickers tilldelad ["IPCO.ST", ""] igen då .strip() bara tar bort whitespace len(tickers) # är fortfarande 2 # lägger du till filter efter strip så bör du inte få en tom "axes" tickers = list(filter(None, tickers)) len(tickers) # = 1

Ok nu lärde jag mig något nu måste jag bara lösa det där med "TypeError: 'Axes' object is not subscriptable" fattar inte vad det betyder ännu men ska läsa lite nu om det och förhoppningsvis kanske jag kan lägga upp allt på git så andra kan ta del utav detta kommer ge cred where its due om ni inte har några invändningar självklart.

edit: hittade denna men asså jag fattar ingenting https://github.com/sustainability-lab/vayu/issues/54 men denna förklarar mycket: https://blog.finxter.com/fixed-matplotlib-typeerror-axessubpl...

Så om jag förstår det rätt - så kan jag inte programmera alls som jag gjort, då nästan all min kod är axes[idx].plot....
jag undrar hur jag ska göra ;/ får bli mer läsning nu.

Nu när sweanisse uppdaterat ser jag hur han har gjort för att få det att fungera, och han har skrivit kommentarer på allt så jag fattar nu vad som händer också, tack så hemskt mycket! din kod var bättre

Permalänk
Medlem
Skrivet av Vetulus:

Ok nu lärde jag mig något nu måste jag bara lösa det där med "TypeError: 'Axes' object is not subscriptable" fattar inte vad det betyder ännu men ska läsa lite nu om det och förhoppningsvis kanske jag kan lägga upp allt på git så andra kan ta del utav detta kommer ge cred where its due om ni inte har några invändningar självklart.

edit: hittade denna men asså jag fattar ingenting https://github.com/sustainability-lab/vayu/issues/54 men denna förklarar mycket: https://blog.finxter.com/fixed-matplotlib-typeerror-axessubpl...

Så om jag förstår det rätt - så kan jag inte programmera alls som jag gjort, då nästan all min kod är axes[idx].plot....
jag undrar hur jag ska göra ;/ får bli mer läsning nu

Du får väl bara not subscriptable problemet om du kör in 1 ticker istället för fler?

Permalänk
Medlem
Skrivet av pine-orange:

Du får väl bara not subscriptable problemet om du kör in 1 ticker istället för fler?

det här var lösningen, och ja, det skedde bara när man hade en ticker @sweanisse förklarar allt bra också

# Skapa subplots baserat på antalet tickers. # Hantera fallet med en enda ticker specifikt för att säkerställa att 'axes' # alltid är en itererbar sekvens (lista eller numpy array) för att loopen ska fungera. if len(tickers) == 1: # plt.subplots(1, 1) returnerar en figur och ett enda Axes-objekt. fig, axes_obj = plt.subplots(1, 1) # Vi omsluter det enda Axes-objektet i en lista så att loopen alltid kan använda axes[idx]. axes = [axes_obj] else: # För flera tickers returnerar plt.subplots en figur och en numpy array av Axes-objekt. # Vi använder squeeze=False för att säkerställa att 'axes' alltid är en 2D-array # även om det bara är en kolumn (len(tickers), 1). Därefter plattar vi till den. fig, axes = plt.subplots(len(tickers), 1, squeeze=False) # Plattar till numpy-arrayen till en 1D-array för enklare indexering (axes[idx]) axes = axes.flatten() # Skapa animationen. 'update_graphs' kallas med intervallet 60000 ms (1 minut). # cache_frame_data=False är bra när du hämtar ny realtidsdata varje gång. ani = FuncAnimation(fig, update_graphs, interval=60000, cache_frame_data=False)

@sweanisse

hur nödvändigt är detta egentligen, alltså vad tillför nedan kod som min inte gjorde?

# Vi har nu säkerställt att 'axes' är en itererbar sekvens, # så axes[idx] kommer att ge rätt Axes-objekt. current_ax = axes[idx] current_ax.clear() # Rensa den befintliga grafen innan ny data ritas current_ax.plot(datetime_index, closing, label="Stängningskurs", color="green") current_ax.plot(............

Permalänk

Den här delen är helt nödvändig när du har flera grafer (subplots) som du vill uppdatera individuellt. Här är varför:

  1. axes är en samling: När du anropar plt.subplots(len(tickers), 1, ...) får du tillbaka en figur (fig) och en samling av axlar (subplots), lagrade i variabeln axes. Om du har 3 tickers får du 3 axlar. axes är i princip en lista eller en NumPy-array som innehåller referenser till varje enskild subplot.

  2. Rita på rätt ställe: Matplotlibs ritningskommandon (.plot(), .clear(), .set_title(), .set_xlabel(), .twinx(), etc.) är metoder som anropas på ett specifikt "axes"-objekt. Du ritar inte bara "en linje", du ritar "en linje på den här specifika axeln".

  3. Välja rätt axel: Linjen current_ax = axes[idx] gör just detta. I varje iteration av loopen (for idx, ticker in enumerate(tickers):) hämtar den den korrekta axeln från samlingen axes som motsvarar den aktuella tickern (tickers[idx]). Variabeln current_ax blir då en referens till just den subploten.

  4. Kommandon på specifik axel: Alla de efterföljande rit- och konfigurationskommandona (current_ax.clear(), current_ax.plot(...), current_ax.set_title(...), etc.) tillämpas sedan endast på den axeln som current_ax refererar till.

  5. Rensa gamla data: current_ax.clear() är kritisk för animationen. Eftersom du hämtar ny data varje minut och ritar om grafen, måste du rensa bort den gamla grafen från just den axeln innan du ritar den nya. Annars skulle de nya linjerna ritas ovanpå de gamla, och grafen skulle snabbt bli oläsbar.

Vad tillför det jämfört med en version utan det?

  • Om du inte hämtade den specifika axeln (current_ax = axes[idx]) och anropade metoderna på den, skulle Matplotlib antingen:

  • Försöka rita allt på den senast aktiva axeln (vilket troligen skulle vara den sista subploten i listan, så alla tickers skulle ritas i samma graf).

  • Eller helt enkelt inte veta var den ska rita och potentiellt krascha eller ge oväntat beteende.

Så, sammanfattningsvis: Kodsnutten är absolut nödvändig för att säkerställa att datan för varje specifik ticker ritas på dess egen, korrekta och rensade subplot i figuren, vilket är grunden för att visa flera grafer samtidigt och uppdatera dem individuellt i en animation.

Permalänk
Medlem
Skrivet av sweanisse:

Den här delen är helt nödvändig när du har flera grafer (subplots) som du vill uppdatera individuellt. Här är varför:

  1. axes är en samling: När du anropar plt.subplots(len(tickers), 1, ...) får du tillbaka en figur (fig) och en samling av axlar (subplots), lagrade i variabeln axes. Om du har 3 tickers får du 3 axlar. axes är i princip en lista eller en NumPy-array som innehåller referenser till varje enskild subplot.

  2. Rita på rätt ställe: Matplotlibs ritningskommandon (.plot(), .clear(), .set_title(), .set_xlabel(), .twinx(), etc.) är metoder som anropas på ett specifikt "axes"-objekt. Du ritar inte bara "en linje", du ritar "en linje på den här specifika axeln".

  3. Välja rätt axel: Linjen current_ax = axes[idx] gör just detta. I varje iteration av loopen (for idx, ticker in enumerate(tickers):) hämtar den den korrekta axeln från samlingen axes som motsvarar den aktuella tickern (tickers[idx]). Variabeln current_ax blir då en referens till just den subploten.

  4. Kommandon på specifik axel: Alla de efterföljande rit- och konfigurationskommandona (current_ax.clear(), current_ax.plot(...), current_ax.set_title(...), etc.) tillämpas sedan endast på den axeln som current_ax refererar till.

  5. Rensa gamla data: current_ax.clear() är kritisk för animationen. Eftersom du hämtar ny data varje minut och ritar om grafen, måste du rensa bort den gamla grafen från just den axeln innan du ritar den nya. Annars skulle de nya linjerna ritas ovanpå de gamla, och grafen skulle snabbt bli oläsbar.

Vad tillför det jämfört med en version utan det?

  • Om du inte hämtade den specifika axeln (current_ax = axes[idx]) och anropade metoderna på den, skulle Matplotlib antingen:

  • Försöka rita allt på den senast aktiva axeln (vilket troligen skulle vara den sista subploten i listan, så alla tickers skulle ritas i samma graf).

  • Eller helt enkelt inte veta var den ska rita och potentiellt krascha eller ge oväntat beteende.

Så, sammanfattningsvis: Kodsnutten är absolut nödvändig för att säkerställa att datan för varje specifik ticker ritas på dess egen, korrekta och rensade subplot i figuren, vilket är grunden för att visa flera grafer samtidigt och uppdatera dem individuellt i en animation.

Tack för förtydligandet har lärt mig jättemycket med det här projektet tack vare alla er!