J'ai une série chronologique DataFrame et je veux trouver les valeurs constantes des lignes correspondant aux valeurs d'autres lignes. Supposons que ce soit le DF:
temp = [27.18, 27.18, 27.18, 27.18, 20.82, 20.82, 20.82, 20.82, 15.18,
15.18, 15.18, 15.18, 15.24, 15.24, 15.24, 15.24, 20.4 , 20.4 ,
20.4 , 20.4 , 21.48, 21.48, 21.48, 21.48, 27.66, 27.66, 27.66,
27.66, 27.9 , 27.9 , 27.9 , 27.9 , 27.9 , 27.9 , 27.9 , 27.9 ,
27.84, 27.84, 27.84, 27.84, 27.84, 27.84, 27.84, 27.84, 21.72,
21.72, 21.72, 21.72]
heat = [11.94, 12. , 10.56, 6. , 6. , 6. , 6. , 6. , 6. ,
6. , 6. , 6. , 6. , 6.78, 9. , 9. , 9. , 9. ,
9. , 9. , 9. , 11.58, 12. , 11.94, 11.94, 12. , 12. ,
11.94, 11.94, 12. , 11.94, 12. , 11.94, 12. , 12. , 11.94,
12. , 11.94, 11.94, 12. , 11.94, 9.48, 9. , 9. , 9. ,
9. , 8.94, 9. ]
date = ['2016-01-29 12:00:00', '2016-01-29 12:15:00',
'2016-01-29 12:30:00', '2016-01-29 12:45:00',
'2016-01-29 13:00:00', '2016-01-29 13:15:00',
'2016-01-29 13:30:00', '2016-01-29 13:45:00',
'2016-01-29 14:00:00', '2016-01-29 14:15:00',
'2016-01-29 14:30:00', '2016-01-29 14:45:00',
'2016-01-29 15:00:00', '2016-01-29 15:15:00',
'2016-01-29 15:30:00', '2016-01-29 15:45:00',
'2016-01-29 16:00:00', '2016-01-29 16:15:00',
'2016-01-29 16:30:00', '2016-01-29 16:45:00',
'2016-01-29 17:00:00', '2016-01-29 17:15:00',
'2016-01-29 17:30:00', '2016-01-29 17:45:00',
'2016-01-29 18:00:00', '2016-01-29 18:15:00',
'2016-01-29 18:30:00', '2016-01-29 18:45:00',
'2016-01-29 19:00:00', '2016-01-29 19:15:00',
'2016-01-29 19:30:00', '2016-01-29 19:45:00',
'2016-01-29 20:00:00', '2016-01-29 20:15:00',
'2016-01-29 20:30:00', '2016-01-29 20:45:00',
'2016-01-29 21:00:00', '2016-01-29 21:15:00',
'2016-01-29 21:30:00', '2016-01-29 21:45:00',
'2016-01-29 22:00:00', '2016-01-29 22:15:00',
'2016-01-29 22:30:00', '2016-01-29 22:45:00',
'2016-01-29 23:00:00', '2016-01-29 23:15:00',
'2016-01-29 23:30:00', '2016-01-29 23:45:00']
df = pd.DataFrame(date, columns=['date'])
df.insert(1 ,'temp', temp, True)
df.insert(2, 'heat', heat, True )
df.index = df.date
del df['date']
Le graphique ressemble à ceci:
Je dois trouver la zone marquée entre deux lignes jaunes où les valeurs sont presque constantes et n'ont pas la zone de rampe. J'utilise la méthode de décalage ici mais cela ne fonctionne pas de manière très optimale. Toute idée de comment y parvenir merci d'avance.
méthode de décalage que j'essaye
df.heat! = df.heat.shift (1)). cumsum ()
sortie souhaitée:
3 Réponses :
Ce masque de tracé est-il celui que vous recherchez:
df[df.temp.duplicated() & df.heat.duplicated()].plot()
avec cette fonction, j'obtiens un meilleur tracé mais il y a encore une zone de rampe dans le tracé
le graphique doit être en ligne droite où aucune fluctuation ne se produit. cela signifie que la chaleur et la température deviennent toutes deux constantes.
La deuxième tentative:
# List the times:
rng=np.arange(len(df)) # serves as key for groupby
G= df.groupby( df.const.replace({1:np.nan,np.nan:rng}).ffill().where(crit,np.nan) )
for key,grp in G.groups.items():
t1,t2=grp[0],grp[-1]
if t1!=t2:
print(f"{t1}\n{t2}\n")
2016-01-29 13:15:00
2016-01-29 13:45:00
2016-01-29 14:15:00
2016-01-29 15:00:00
2016-01-29 16:15:00
2016-01-29 16:45:00
2016-01-29 17:30:00
2016-01-29 17:45:00
2016-01-29 18:15:00
2016-01-29 22:00:00
2016-01-29 22:30:00
2016-01-29 22:45:00
2016-01-29 23:15:00
2016-01-29 23:45:00
Tracé:
thtemp=0.5 # threshold thheat=0.5 crit= df.temp.diff().abs().lt(thtemp) & df.heat.diff().abs().lt(thheat) df["const"]= crit.astype(int).replace(0,np.nan)
MODIFIER: Il s'agissait de la première solution mais ne fournissait pas tous les segments constants:
vrep=13
#vrep= (df.temp.mean()+df.heat.mean())/2
for key,grp in G:
if len(grp)>1:
ser= grp.const.replace(key,vrep).reindex(df.index)
plt.plot(ser.index,ser,color="orange", linewidth=2)
plt.plot(df.index,df.temp,color="darkgreen",label="temp")
plt.plot(df.index,df.heat,color="darkblue",label="heat")
plt.legend(loc="best")
plt.grid()
plt.show()
df= pd.DataFrame({"temp":temp,"heat":heat}, index= pd.to_datetime(date) )
thtemp=0.5 # threshold
thheat=0.5
crit= df.temp.diff().abs().lt(thtemp) & df.heat.diff().abs().lt(thheat)
rng=np.arange(1,len(df)+1)
df["const"]= np.where(crit.eq(False),rng,np.nan)
df["const"]= df.const.ffill()
temp heat const
2016-01-29 12:00:00 27.18 11.94 1.0
2016-01-29 12:15:00 27.18 12.00 1.0
2016-01-29 12:30:00 27.18 10.56 3.0
2016-01-29 12:45:00 27.18 6.00 4.0
2016-01-29 13:00:00 20.82 6.00 5.0
2016-01-29 13:15:00 20.82 6.00 5.0
2016-01-29 13:30:00 20.82 6.00 5.0
2016-01-29 13:45:00 20.82 6.00 5.0
2016-01-29 14:00:00 15.18 6.00 9.0
2016-01-29 14:15:00 15.18 6.00 9.0
2016-01-29 14:30:00 15.18 6.00 9.0
2016-01-29 14:45:00 15.18 6.00 9.0
2016-01-29 15:00:00 15.24 6.00 9.0
...
G= df.groupby(df.const)
for key,grp in G:
if len(grp)>1:
print(f"\t{grp.index[0]}\n\t{grp.index[-1]}\n")
2016-01-29 12:00:00
2016-01-29 12:15:00
2016-01-29 13:00:00
2016-01-29 13:45:00
2016-01-29 14:00:00
2016-01-29 15:00:00
2016-01-29 15:30:00
2016-01-29 15:45:00
2016-01-29 16:00:00
2016-01-29 16:45:00
2016-01-29 17:15:00
2016-01-29 17:45:00
2016-01-29 18:00:00
2016-01-29 22:00:00
2016-01-29 22:15:00
2016-01-29 22:45:00
2016-01-29 23:00:00
2016-01-29 23:45:00
Merci pour la réponse, cela fonctionne parfaitement. Juste une chose ici: la constante 2016-01-29 13:15:00 2016-01-29 13:45:00 commence à 13:00:00. Puis-je l'obtenir aussi, si possible. Et comment avez-vous tracé la ligne constante rouge
@Arpit Le problème des segments manquants est résolu, voir ci-dessus.
Merci beaucoup! Ceci est exactement ce que je cherchais!
En développant la réponse acceptée actuelle, créez votre dataframe
import matplotlib.pyplot as plt import numpy as np fig, ax = plt.subplots() ax.plot(df.index, df['temp']) ax.plot(df.index, df['heat']) ax.fill_between(df.index, 0, 1, where=df['const'], alpha=0.1, transform=ax.get_xaxis_transform()) plt.gcf().autofmt_xdate() plt.show()
créez une variable booléenne qui est True lorsque les valeurs sont constantes
thtemp=0.5 # threshold
thheat=0.5
df["const"] = df.temp.diff().abs().lt(thtemp) & df.heat.diff().abs().lt(thheat)
df.head()
temp heat const
date
2016-01-29 12:00:00 27.18 11.94 False
2016-01-29 12:15:00 27.18 12.00 True
2016-01-29 12:30:00 27.18 10.56 False
2016-01-29 12:45:00 27.18 6.00 False
2016-01-29 13:00:00 20.82 6.00 False
trace et remplissez la zone lorsque const == True
import pandas as pd
temp = [27.18, 27.18, 27.18, 27.18, 20.82, 20.82, 20.82, 20.82, 15.18,
15.18, 15.18, 15.18, 15.24, 15.24, 15.24, 15.24, 20.4 , 20.4 ,
20.4 , 20.4 , 21.48, 21.48, 21.48, 21.48, 27.66, 27.66, 27.66,
27.66, 27.9 , 27.9 , 27.9 , 27.9 , 27.9 , 27.9 , 27.9 , 27.9 ,
27.84, 27.84, 27.84, 27.84, 27.84, 27.84, 27.84, 27.84, 21.72,
21.72, 21.72, 21.72]
heat = [11.94, 12. , 10.56, 6. , 6. , 6. , 6. , 6. , 6. ,
6. , 6. , 6. , 6. , 6.78, 9. , 9. , 9. , 9. ,
9. , 9. , 9. , 11.58, 12. , 11.94, 11.94, 12. , 12. ,
11.94, 11.94, 12. , 11.94, 12. , 11.94, 12. , 12. , 11.94,
12. , 11.94, 11.94, 12. , 11.94, 9.48, 9. , 9. , 9. ,
9. , 8.94, 9. ]
date = ['2016-01-29 12:00:00', '2016-01-29 12:15:00',
'2016-01-29 12:30:00', '2016-01-29 12:45:00',
'2016-01-29 13:00:00', '2016-01-29 13:15:00',
'2016-01-29 13:30:00', '2016-01-29 13:45:00',
'2016-01-29 14:00:00', '2016-01-29 14:15:00',
'2016-01-29 14:30:00', '2016-01-29 14:45:00',
'2016-01-29 15:00:00', '2016-01-29 15:15:00',
'2016-01-29 15:30:00', '2016-01-29 15:45:00',
'2016-01-29 16:00:00', '2016-01-29 16:15:00',
'2016-01-29 16:30:00', '2016-01-29 16:45:00',
'2016-01-29 17:00:00', '2016-01-29 17:15:00',
'2016-01-29 17:30:00', '2016-01-29 17:45:00',
'2016-01-29 18:00:00', '2016-01-29 18:15:00',
'2016-01-29 18:30:00', '2016-01-29 18:45:00',
'2016-01-29 19:00:00', '2016-01-29 19:15:00',
'2016-01-29 19:30:00', '2016-01-29 19:45:00',
'2016-01-29 20:00:00', '2016-01-29 20:15:00',
'2016-01-29 20:30:00', '2016-01-29 20:45:00',
'2016-01-29 21:00:00', '2016-01-29 21:15:00',
'2016-01-29 21:30:00', '2016-01-29 21:45:00',
'2016-01-29 22:00:00', '2016-01-29 22:15:00',
'2016-01-29 22:30:00', '2016-01-29 22:45:00',
'2016-01-29 23:00:00', '2016-01-29 23:15:00',
'2016-01-29 23:30:00', '2016-01-29 23:45:00']
df = pd.DataFrame({'date': date, 'temp': temp, 'heat': heat})
df.index = pd.to_datetime(df['date'],infer_datetime_format=True)
del df['date']
Pourquoi créez-vous le dataframe si compliqué?
C'est un échantillon des données originales avec quelques modifications
Je peux voir quatre régions où le df a des lignes constantes, et la paire de lignes jaunes la plus à droite n'en fait pas partie.
J'ai besoin de trouver la zone où la chaleur et la température sont relativement constantes l'une par rapport à l'autre.
"Relativement constant"! = "Constant". Vous devez être très clair sur ce que vous voulez
Je voulais dire la zone où la chaleur et la température deviennent toutes deux constantes. Ils n'ont pas de fluctuations de valeurs
Je suggère quelque chose comme
df = pd.DataFrame ({'temp': temp, 'heat': heat}, index = date)Vous pourriez faire une fusion interne sur les colonnes que vous voulez en tant que constantes? puis tracez-les.
Quelle est la commande plot que vous utilisez?
avec la méthode de décalage, je peux trouver les valeurs constantes de la chaleur. Mais les données ne sont pas bonnes et il y a des horodatages où la chaleur est constante mais la température ne l'est pas. Je dois considérer ces deux et ensuite trouver la zone constante
@oppressionslayer juste df.plot ()