1
votes

Comment itérer sur les lignes pour trouver les valeurs constantes des colonnes dans les pandas

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:

 entrez la description de l'image ici

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:

 entrez la description de l'image ici a >


11 commentaires

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 ()


3 Réponses :


0
votes

Ce masque de tracé est-il celui que vous recherchez:

df[df.temp.duplicated() & df.heat.duplicated()].plot()


2 commentaires

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.



2
votes

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)

 entrez la description de l'image ici

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()

entrez la description de l'image ici

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


3 commentaires

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!



0
votes

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']

entrez la description de l'image ici


0 commentaires