1
votes

Pandas: recherche des valeurs de début et de fin d'index consécutifs dans une trame de données Pandas

J'ai un dataframe qui ressemble à ceci ( main_df ):

import pandas as pd

filepath=r'C:\Users\myfile.csv'
main_df=pd.read_csv(filepath)
main_df['created_at']=main_df['created_at'].apply(pd.to_datetime)
main_df['created_at'] = main_df['created_at'].dt.tz_localize('UTC').dt.tz_convert('EST')

Je veux localiser des segments de valeurs nulles répétées dans la colonne "valeur". Je sais comment localiser les zéros, en faisant simplement ceci:

aux_df2['t_diff'] = ['temp_index'].diff().astype('timedelta64[m]')

Ce qui me laisserait le dataframe suivant ( aux_df1 ): aux_df1

Maintenant, ce que j'aimerais obtenir, et je ne sais pas comment, c'est de ne conserver que le début et le début de chaque série d'index consécutifs dans un nouveau dataframe nommé aux_df2 , et calculez la différence de temps entre le début et la fin de chaque série de valeurs consécutives en minutes. J'ai l'intention de faire la dernière partie avec ceci (bien que j'aimerais calculer la différence juste par paires, entre chaque paire début-fin):

zeros_df=main_df.loc[main_df['value'] == 0]

Mais la première partie Je ne sais pas comment faire. Ce que je recherche, c'est que aux_df2 ressemble à ceci:

aux_df2

Quelqu'un peut-il m'aider s'il vous plaît ? Merci d'avance.

Edit: en réponse à @peer, voici comment je génère le dataframe. Notez que les instantanés ci-dessus ne reflètent pas le changement de fuseau horaire entre UTC et EST.

           value               created_at
0   18.930542  2019-03-04 02:43:08 UTC
1   18.895210  2019-03-04 02:44:09 UTC
2    0.000000  2019-03-04 02:45:09 UTC
3    0.000000  2019-03-04 02:46:10 UTC
4    0.000000  2019-03-04 02:47:11 UTC
5    0.000000  2019-03-04 02:48:12 UTC
6    0.000000  2019-03-04 02:49:13 UTC
7   18.857025  2019-03-04 02:50:14 UTC
8   18.857025  2019-03-04 02:51:14 UTC
9   18.847290  2019-03-04 02:52:15 UTC
10  18.847290  2019-03-04 02:53:17 UTC
11   0.000000  2019-03-04 02:54:17 UTC
12   0.000000  2019-03-04 02:55:19 UTC
13   0.000000  2019-03-04 02:56:19 UTC
14  18.837677  2019-03-04 02:57:20 UTC


6 commentaires

pourriez-vous fournir le code qui génère l'exemple d'ensemble de données? Cela nous permettra de vous aider plus facilement.


Salut @peer, je télécharge ces données à partir d'un fichier .csv, ce n'est qu'un très petit échantillon de l'ensemble. Tout ce que j'ai fait jusqu'à présent est de convertir les fuseaux horaires UTC en EST et de changer le type de la colonne datetime d'objet en datetime correct. Je posterai quand même une modification avec. Mais dans les instantanés, je n'ai laissé que des informations pertinentes, je n'ai même pas changé le fuseau horaire approprié.


@ AquilesPáez ce qu'il veut dire, c'est que nous ne pouvons pas copier vos captures d'écran. Est-il possible de imprimer () ces exemples que vous montrez dans la capture d'écran et de coller le résultat dans votre question afin que nous puissions le copier.


Mec, ça va être pénible d'essayer de faire cela sans exemple de dataframe. Je vous suggère de télécharger un petit fichier csv sur github et de partager un lien vers celui-ci afin que nous puissions obtenir des données avec lesquelles travailler.


@Erfan désolé, c'est fait!


@SamuelNde oui, mon mal. Je l'ai changé là-bas.


3 Réponses :


1
votes

Sur la base des informations que vous avez incluses, j'ai fait quelque chose comme ceci:

import pandas as pd
import numpy as np
df = pd.DataFrame({"index":[2,3,4,5,6,11,12,13],"value": [0,0,0,0,0,0,0,0]})
df["prev_index"] = df["index"].shift(1)
df["next_index"] = df["index"].shift(-1)

df["include"] = df.apply(lambda row: True if np.isnan(row.next_index) or np.isnan(row.prev_index)
         else (True if abs(row["index"]-row.next_index) != 1 
               or abs(row["index"] - row.prev_index) != 1 else False),axis=1)
df[df["include"]][["index","value"]]

J'ai créé une simple trame de données à partir de l'échantillon que vous avez donné, donc mon idée est simplement de déplacer l'ensemble de données afin de obtenir l'index précédent et suivant, basé sur les deux colonnes, je viens de créer un booléen pour savoir si l'index est celui que je recherche. J'espère que ça aide!


1 commentaires

Merci pour votre contribution! Ok, je peux utiliser cela pour faire une indexation bien que ce ne soit pas exactement ce que je veux.



4
votes

Votre t_diff attendu ne semble pas correct, mais voici une solution utilisant np.ptp qui prend le maximum - minimum sur une plage et pandas.Series.cumsum

I utilisé cumsum car de cette façon nous pouvons trouver les lignes qui sont 0

df['cumsum'] = df.value.cumsum()

df['t_diff'] = df.groupby('cumsum').created_at.transform(np.ptp)
df.drop('cumsum', axis=1, inplace=True)

print(df)
    Index      value          created_at   t_diff
0       0  18.930542 2019-03-04 02:43:08 00:00:00
1       1  18.895210 2019-03-04 02:44:09 00:05:04
2       2   0.000000 2019-03-04 02:45:09 00:05:04
3       3   0.000000 2019-03-04 02:46:10 00:05:04
4       4   0.000000 2019-03-04 02:47:11 00:05:04
5       5   0.000000 2019-03-04 02:48:12 00:05:04
6       6   0.000000 2019-03-04 02:49:13 00:05:04
7       7  18.857025 2019-03-04 02:50:14 00:00:00
8       8  18.857025 2019-03-04 02:51:14 00:00:00
9       9  18.847290 2019-03-04 02:52:15 00:00:00
10     10  18.847290 2019-03-04 02:53:17 00:03:02
11     11   0.000000 2019-03-04 02:54:17 00:03:02
12     12   0.000000 2019-03-04 02:55:19 00:03:02
13     13   0.000000 2019-03-04 02:56:19 00:03:02
14     14  18.837677 2019-03-04 02:57:20 00:00:00

note dans ce cas, je transforme pour obtenir la différence à côté de chaque ligne du groupe.


2 commentaires

C'est parfait et élégant. Vraiment, je ne savais pas que c'était possible, bien que Pandas soit réputé pour être puissant pour la manipulation de données. Je faisais quelque chose avec des cycles for / if avant de décider de poster cette question, content de l'avoir fait. Et oui, j'ai besoin d'acquérir plus de profondeur avec les Pandas. Merci beaucoup Erfan! :)


Heureux de pouvoir aider :) et oui je suis d'accord sur le fait que les pandas sont élégants et puissants. Bon codage @ AquilesPáez



0
votes

Un peu en retard au jeu ici, mais j'aimerais proposer ma solution pour trouver le début et la fin en utilisant le filtrage de la valeur et le diff de la valeur:

      value              created_at
2     0.0 2019-03-04 02:45:09+00:00
6     0.0 2019-03-04 02:49:13+00:00
11    0.0 2019-03-04 02:54:17+00:00
13    0.0 2019-03-04 02:56:19+00:00

Ceci donne:

aux_df2 = main_df[
(main_df['value'] == 0) &
(
    (main_df['value'].diff() != 0)
    | main_df['value'].diff().shift(-1) != 0
)]

Je ne peux pas penser à une manière élégante d'obtenir t_diff, cependant.


0 commentaires