Topic: Rottura linea di tendenza con Matplotlib  (Letto 134 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline PyAnam

  • python unicellularis
  • *
  • Post: 9
  • Punti reputazione: 0
    • Mostra profilo
Rottura linea di tendenza con Matplotlib
« il: Dicembre 04, 2021, 19:36 »
Salve, nel programma che segue viene individuata una retta di tendenza analizzando i valori di una lista .csv (esclusi i due più recenti in ordine di tempo) ed in seguito viene plottato il grafico con i valori e la retta di tendenza ottenuta. (grazie a nuzzopippo per il suo importantissimo contributo)
Quello che non riesco a fare è verificare se l'ultimo valore (in ordine di tempo il più recente) oppure il penultimo sono maggiori della retta di tendenza e quindi se c'è una rottura del trend riportato a grafico.


import csv
import pandas as pd
from matplotlib import pyplot as plt

with open('pyanam.csv', 'r') as f:
    data = data = list(csv.DictReader(f, delimiter=','))
    rimuovi=data.pop(0)
    rimuovi2 = data.pop(0)
    data

for r in data:
print(r)

def get_p_min_vertex(d):
    data = d[::-1]
    elements = []
    m_value = str(max([int(x['fee']) for x in data]))
    for i in range(len(data)):
        if data[i]['fee'] == m_value:
            p = data[i]
            elements.append(p)
            break
    sd = data[i + 1:]
    rapp = [(int(p['fee']) - int(x['fee'])) / (int(x['time']) - int(p['time'])) for x in sd]
    i_r = rapp.index(min(rapp))
    s = sd[i_r]
    elements.append(s)
    return elements

p, s = get_p_min_vertex(data)
print('Max ',p)
print('Min',s)

def crea_retta(x1,y1,x2,y2):
    if x1==x2 and y1==y2:
        raise ValueError("Infinite rette")
    elif x1==x2:
        raise ValueError("Equazione nella forma x=q")
    else:
        m=float(y2-y1)/(x2-x1)
        q=y1-(m*x1)
    def retta(x):
        return m*x+q
    return retta

############################

csv = pd.read_csv('pyanam.csv')
data = csv[['fee', 'time']]

print(data)
x = data['time']
y = data['fee']
plt.plot(x,y,marker='o',color='blue', label = 'line 1')

try:
    r = crea_retta(int(p['time']), int(p['fee']),
                   int(s['time']), int(s['fee']))
except ValueError as e:
    print(format(e))
    r = None
x_min = min(data['time'])
x_max = max(data['time'])

plt.plot([n for n in range(x_min, x_max)], [r(n) for n in range(x_min, x_max)],
         marker='o',linestyle='-.',color='red', label = 'line 2')
plt.xlabel('TIME')
plt.ylabel('RSI VALUE')
plt.title('Grafico RSI')
print('questo è rimosso: ',rimuovi)
print('questo è rimosso: ', rimuovi2)
plt.show()


pyanam.csv


fee,time
500,100
724,95
127,93
700,90
477,87
200,83
860,80
1300,75
800,70
1000,60
850,50
1100,40
1050,30
« Ultima modifica: Dicembre 04, 2021, 19:38 da PyAnam »

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 541
  • Punti reputazione: 0
    • Mostra profilo
Re:Rottura linea di tendenza con Matplotlib
« Risposta #1 il: Dicembre 04, 2021, 20:59 »
Ora è tardi per esplicitare un esempio ma la soluzione dovresti averla già : la funzione "crea_retta" Ti restituisce una funzione che data una ordinata calcola l'ascissa sulla equazione della retta, è sufficiente verificare se il "fee" corrispondente è maggiore o minore al risultato della funzione per il time, se fee è maggiore vi è una rottura del trend.

[Edit] Allora, come dicevo ieri, hai già tutti gli elementi che Ti servono, applica l'equazione della retta al time dei punti "rimossi" per calcolare l'ascissa della retta, se il fee di un punto la supera, in quel punto è avvenuta una interruzione di tendenza, modifica la parte finale del Tuo codice così:

msg = 'questo è rimosso: ' + repr(rimuovi)
lim_for = r(int(rimuovi['time']))
if int(rimuovi['fee']) > lim_for:
    msg += ' - linea tendenza interrotta'
else:
    msg += ' - linea tendenza OK'
print(msg)
msg = 'questo è rimosso: ' + repr(rimuovi2)
lim_for = r(int(rimuovi2['time']))
if int(rimuovi2['fee']) > lim_for:
    msg += ' - linea tendenza interrotta'
else:
    msg += ' - linea tendenza OK'
print(msg)
plt.show()

avrai questi messaggi nel terminale:
12  1050    30
questo è rimosso: {'fee': '500', 'time': '100'} - linea tendenza OK
questo è rimosso: {'fee': '724', 'time': '95'} - linea tendenza OK
>>>


a riprova modifica il punto {'fee': '724', 'time': '95'} a {'fee': '960', 'time': '95'} (nel csv, ovvio) avrai come output
12  1050    30
questo è rimosso: {'fee': '500', 'time': '100'} - linea tendenza OK
questo è rimosso: {'fee': '960', 'time': '95'} - linea tendenza interrotta
>>>

ed il grafico Te ne darà conferma.

Ciao
« Ultima modifica: Dicembre 05, 2021, 09:23 da nuzzopippo »

Offline PyAnam

  • python unicellularis
  • *
  • Post: 9
  • Punti reputazione: 0
    • Mostra profilo
Re:Rottura linea di tendenza con Matplotlib
« Risposta #2 il: Dicembre 07, 2021, 11:32 »
così è perfetta, grazie mille!!!!

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 541
  • Punti reputazione: 0
    • Mostra profilo
Re:Rottura linea di tendenza con Matplotlib
« Risposta #3 il: Dicembre 07, 2021, 11:48 »
Prego @PyAnam

... come vedi si tratta, comunque, di geometria elementare, è esattamente il "triangolo rettangolo" dell'altro post ciò che risolve ;)