2017-06-27 7 views
2

Ich habe eine (sehr vereinfachter hier) Pandas Datenrahmen, die wie folgt aussieht:Pandas Datenrahmen: Duplikate basierend auf Spalte und Zeitbereich

df

datetime    user type msg 
0 2012-11-11 15:41:08 u1  txt hello world 
1 2012-11-11 15:41:11 u2  txt hello world 
2 2012-11-21 17:00:08 u3  txt hello world 
3 2012-11-22 18:08:35 u4  txt  hello you 
4 2012-11-22 18:08:37 u5  txt  hello you 

Was Ich mag würde jetzt zu tun ist, zu erhalten Alle doppelte Nachrichten, deren Zeitstempel innerhalb von 3 Sekunden ist. Die gewünschte Ausgabe wäre:

datetime    user type msg 
0 2012-11-11 15:41:08 u1  txt hello world 
1 2012-11-11 15:41:11 u2  txt hello world 
3 2012-11-22 18:08:35 u4  txt  hello you 
4 2012-11-22 18:08:37 u5  txt  hello you 

ohne die dritte Reihe, wie der Text die gleichen wie in Zeile eins und zwei ist, aber die Zeitmarke nicht im Bereich von 3 Sekunden.

Ich habe versucht, die Spalten Datetime und msg als Parameter für die duplicate() Methode zu definieren, aber es gibt einen leeren Datenrahmen, da die Zeitstempel nicht identisch sind:

mask = df.duplicated(subset=['datetime', 'msg'], keep=False) 

print(df[mask]) 
Empty DataFrame 
Columns: [datetime, user, type, msg, MD5] 
Index: [] 

Gibt es eine Möglichkeit, wo ich einen Bereich definieren für meinen "datetime" -Parameter? Zur Veranschaulichung etwas wie:

mask = df.duplicated(subset=['datetime_between_3_seconds', 'msg'], keep=False) 

Alle hier helfen würde, wie immer sehr geschätzt werden.

Antwort

1

Dieses Codebeispiel funktioniert mit Ihren Beispieldaten, obwohl Sie möglicherweise mit Extremfällen herumspielen müssen.

Von Ihrer Frage nehme ich an, dass Sie Nachrichten aus dem ersten Mal in df ausfiltern möchten. Es funktioniert nicht, wenn Sie Instanzen haben, in denen Sie die Zeichenfolge beibehalten möchten, wenn sie nach einem anderen Schwellenwert erneut angezeigt wird.

Kurz gesagt, ich schrieb eine Funktion, die Ihr Dataframe und die 'msg' zum Filtern verwendet. Es dauert den Zeitstempel des ersten Mal, dass die Nachricht erscheint und vergleicht das mit allen anderen Zeiten, die es erscheint.

Es wählt dann nur die Instanzen aus, wo es innerhalb von 3 Sekunden nach dem ersten Erscheinen erscheint.

import numpy as np 
    import pandas as pd 
    #function which will return dataframe containing messages within three seconds of the first message 
    def get_info_within_3seconds(df, msg): 
     df_of_msg = df[df['msg']==msg].sort_values(by = 'datetime') 
     t1 = df_of_msg['datetime'].reset_index(drop = True)[0] 
     datetime_deltas = [(i -t1).total_seconds() for i in df_of_msg['datetime']] 
     filter_list = [i <= 3.0 for i in datetime_deltas] 
     return df_of_msg[filter_list] 

    msgs = df['msg'].unique() 
    #apply function to each unique message and then create a new df 
    new_df = pd.concat([get_info_within_3seconds(df, i) for i in msgs]) 
+0

Vielen Dank für Ihre Hilfe, Tkanno! Ihr Vorschlag war auch hilfreich! – dliv

3

Dieses Stück Code gibt die erwartete Ausgabe

df[(df.groupby(["msg"], as_index=False)["datetime"].diff().fillna(0).dt.seconds <= 3).reset_index(drop=True)] 

ich auf „msg“ Spalte von Datenrahmen gruppiert haben und dann „Datetime“ Spalte dieses Datenrahmen ausgewählt und verwendet eingebaute Funktion diff. Die Diff-Funktion ermittelt den Unterschied zwischen den Werten dieser Spalte. Befüllte die NaT-Werte mit Null und wählte nur die Indizes aus, die Werte von weniger als 3 Sekunden haben.

Bevor Sie den obigen Code verwenden, stellen Sie sicher, dass Ihr Dataframe nach Datum und Uhrzeit in aufsteigender Reihenfolge sortiert ist.

+0

Wenn meine Antwort hilfreich war, vergiss nicht, sie zu akzeptieren. Danke –

+0

Ja, akzeptiert, vielen Dank für Ihre Hilfe (und Entschuldigung für die Verzögerung)! Es macht, was ich brauchte. – dliv

+0

@dliv danke für die Abstimmung die Antwort. Ich bin froh, dass ich dir helfen kann. Bitte überprüfen Sie diesen Link zur [akzeptieren] (https://stackoverflow.com/help/accepted-answer) Antwort. –

Verwandte Themen