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 ):
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:
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
3 Réponses :
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!
Merci pour votre contribution! Ok, je peux utiliser cela pour faire une indexation bien que ce ne soit pas exactement ce que je veux.
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.
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
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.
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.