J'ai dataframe df:
Id timestamp data sig events1 Start Peak Timediff Datadiff 104514 104755 2012-03-21 16:23:21.423 20.0 -1.0 0.0 0.0 1.0 0.100 0.5 104623 104864 2012-03-22 04:27:04.550 19.5 0.0 0.0 0.0 0.0 43423.127 -0.5 104630 104871 2012-03-22 04:27:11.670 19.5 -1.0 0.0 0.0 1.0 7.120 0.0 105148 105389 2012-03-23 06:12:24.623 18.5 1.0 1.0 0.0 0.0 0.100 -0.5
Pour les lignes où Timediff == 0.100 et timestamp code > ont la même heure, minute et seconde (par exemple 16: 23: 21.323 et 16: 23: 21.423 ), supprimez le premier de la paire, c.-à-d. 16: 23: 21.323 (la ligne précédente). Comment puis-je faire cela?
Résultat attendu:
Id timestamp data sig events1 Start Peak Timediff Datadiff 104513 104754 2012-03-21 16:23:21.323 19.5 1.0 0.0 1.0 0.0 28732.920 0.5 104514 104755 2012-03-21 16:23:21.423 20.0 -1.0 0.0 0.0 1.0 0.100 0.5 104623 104864 2012-03-22 04:27:04.550 19.5 0.0 0.0 0.0 0.0 43423.127 -0.5 104630 104871 2012-03-22 04:27:11.670 19.5 -1.0 0.0 0.0 1.0 7.120 0.0 105147 105388 2012-03-23 06:12:24.523 19.0 -1.0 0.0 0.0 0.0 92712.853 -0.5 105148 105389 2012-03-23 06:12:24.623 18.5 1.0 1.0 0.0 0.0 0.100 -0.5
3 Réponses :
Il existe peut-être un moyen plus simple d'y parvenir, mais je pense que cela fonctionne compte tenu de vos conditions:
# reset index to make our life easier
df = df.reset_index()
# get rows with small timediffs
small_timediffs = df.loc[df.Timediff <= 0.1]
# get rows immediately above rows with small timediffs
prev_small_timediffs = df.loc[small_timediffs.index-1]
# helper function to allow comparison of timestamps without milisseconds
remove_milisseconds = lambda x: x.split('.')[0]
# compare if timestamps from rows with small timediffs
# and rows above them are the same
stamps = small_timediffs.timestamp.apply(remove_milisseconds).values
prev_stamps = prev_small_timediffs.timestamp.apply(remove_milisseconds).values
cond = (stamps == prev_stamps)
# extract results based on both conditions
# (small timediff and same timestamp)
result = df.loc[~df.index.isin(small_timediffs.loc[cond].index-1)]
Merci pour votre réponse! Il a renvoyé AttributeError: l'objet 'Timestamp' n'a pas d'attribut 'split'
Je devrais voir vos données réelles pour comprendre ce qui ne va pas. Mon code fonctionne lorsque je copie le dataframe de votre question et le charge dans des pandas avec df = pd.read_clipboard .
L'idée est de regrouper les dates et heures de plancher par seconde par Series.dt.floor , puis supprimez la ligne précédente s'il existe au moins un masque correspondant m1:
m1 = df3['Timediff'].eq(0.100) & df3['Start'].ne(1) & df3['Start'].shift(1).ne(1)
MODIFIER: Répondre au commentaire du formulaire avec les constions suivantes:
#convert to datetimes
df['timestamp'] = pd.to_datetime(df['timestamp'])
#test 0.1
m1 = df['Timediff'].eq(0.1)
#test previous values of m1
m2 = m1.shift(-1, fill_value=False)
#test if in groups floored by seconds is at least one True in m1
m3 = m1.groupby([df['timestamp'].dt.floor('S')]).transform('any')
#filter chained m3 with m2 and invert mask
df = df[~(m3 & m2)]
print (df)
Id timestamp data sig events1 Start Peak \
104514 104755 2012-03-21 16:23:21.423 20.0 -1.0 0.0 0.0 1.0
104623 104864 2012-03-22 04:27:04.550 19.5 0.0 0.0 0.0 0.0
104630 104871 2012-03-22 04:27:11.670 19.5 -1.0 0.0 0.0 1.0
105148 105389 2012-03-23 06:12:24.623 18.5 1.0 1.0 0.0 0.0
Timediff Datadiff
104514 0.100 0.5
104623 43423.127 -0.5
104630 7.120 0.0
105148 0.100 -0.5
C'est ce que je veux. Merci pour le code succinct!
Btw j'ai ajouté une autre condition en utilisant df3 ['m1'] = df3 ['Timediff']. Eq (0.100) & df3 ['Start']. Ne (1) & df3 ['Start']. Shift ( 1) .ne (1) (df3 [ Start ] et df3 ['Start']. Shift (1) ne peut pas être 1 code>). Seriez-vous en mesure d'ajouter cette condition à votre code modifié? Merci.
@nilsinelabore - Je suis d'accord, le code est sympa. Il filtre 0.100 et supprime 1,1 valeurs consécutives
Oui. J'ai appris l'astuce à partir du code dans votre réponse précédente; Pouvez-vous modifier votre nouvelle réponse en ajoutant cette condition supplémentaire s'il vous plaît?
@nilsinelabore - Une chose, ça marche correctement? Sinon, est-il possible d'ajouter la sortie attendue par de nouvelles conditions?
Oui, les deux fonctionnent. Je veux juste ajouter une autre condition: pour les lignes où Timediff == 0.100 , et horodatage ont les mêmes heure, minute et seconde (par exemple. 16: 23: 21.323 et 16: 23: 21.423 ), supprimez le premier de la paire, mais si df3 ['Start'] ou df3 ['Start'] .shift (1) vaut 1 pour cette ligne, nous ne supprimons pas la ligne car c'est important .
Ne vous inquiétez pas si c'est trop de problèmes. Votre code précédent fonctionnait parfaitement :)
@nilsinelabore - Je suis un peu confus maintenant, mais j'ai ajouté une solution d'un commentaire à l'autre.
Ouais c'est ce que je veux dire! Désolé pour la confusion. Merci beaucoup :)
Je viens de réaliser un problème, des cas comme 11: 56: 51.980 et 11: 56: 52.080 seront manqués car ils ne partagent pas les mêmes secondes. Existe-t-il un moyen de résoudre ce problème?
J'ai ajouté des valeurs à votre trame de données pour recevoir les mêmes heures, minutes et secondes pour les enregistrements avec une valeur = 0,100
df = pd.DataFrame({'data':['16:23:21.323 19.5','16:23:21.423 20.0','04:27:04.550 19.5',
'04:27:11.670 19.5','06:12:24.523 19.0','06:12:24.623 18.5',
'16:23:21.323 19.5','06:12:24.523 19.0'],
'timestamp':['2012-03-21','2012-03-21','2012-03-22','2012-03-22','2012-03-23','2012-03-23',
'2012-03-23','2012-03-23'],
'timediff':[28732.920,0.100,43423.127,7.120,0.100,0.100,92712.853,0.100]})
df['h_m_s'] = df['data'].str.extract(r'(.*) ')
data timediff timestamp h_m_s
0 16:23:21.323 19.5 28732.920 2012-03-21 16:23:21.323
1 16:23:21.423 20.0 0.100 2012-03-21 16:23:21.423
2 04:27:04.550 19.5 43423.127 2012-03-22 04:27:04.550
3 04:27:11.670 19.5 7.120 2012-03-22 04:27:11.670
4 06:12:24.523 19.0 0.100 2012-03-23 06:12:24.523
5 06:12:24.623 18.5 0.100 2012-03-23 06:12:24.623
6 16:23:21.323 19.5 92712.853 2012-03-23 16:23:21.323
7 06:12:24.523 19.0 0.100 2012-03-23 06:12:24.523
df_same = df[(df.timediff==0.100)]
df = df[~(df.timediff==0.100)]
df_same = df_same.drop_duplicates(subset=['h_m_s'],keep='first')
df=pd.concat([df,df_same])
print(df)
data timediff timestamp h_m_s
0 16:23:21.323 19.5 28732.920 2012-03-21 16:23:21.323
2 04:27:04.550 19.5 43423.127 2012-03-22 04:27:04.550
3 04:27:11.670 19.5 7.120 2012-03-22 04:27:11.670
6 16:23:21.323 19.5 92712.853 2012-03-23 16:23:21.323
1 16:23:21.423 20.0 0.100 2012-03-21 16:23:21.423
4 06:12:24.523 19.0 0.100 2012-03-23 06:12:24.523
5 06:12:24.623 18.5 0.100 2012-03-23 06:12:24.623
L'index de votre dataframe est-il ordonné? Peut-il être réinitialisé?
@jfaccioni Oui. Je pense que cela peut être du repos - y a-t-il des problèmes avec la réinitialisation normale de l'index?
Cela dépend si l'index a une signification pour vous / vos données ou non.
L'agrégation des séries temporelles à une fréquence requise est le meilleur dôme par df.resample ()
@jfaccioni Dans ce cas, je pense que l'index n'a pas de signification particulière.
@nilsinelabore pourriez-vous coller ici le code pour votre exemple de dataframe ad df = pd.Dataframe (data)? il sera plus confortable de vous aider
@wwnde Est-ce que
df.resample ()me permet de spécifier les conditions supplémentaires? Je veux dire que les lignes que je veux supprimer ne se produisent pas à des fréquences fixes (c'est-à-dire pas toutes les autres lignes) mais sont des événements irréguliers dans la trame de données.Indiquez la fréquence. Si indiqué, rééchantillonner choisissez le dernier élément de jour demandé. Par exemple, le mois de rééchantillonnage choisira la dernière date du mois. J'ai trouvé la lecture de la documentation utile car elle contient à la fois des explications et des exemples.