2016-05-18 21 views
1

Ich arbeite mit einem großen Datenrahmen und ich habe Mühe, eine effiziente Möglichkeit zu finden, bestimmte Daten zu beseitigen. Beachten Sie, dass ich versuche, Messungen von einem spezifischen Datum zu beseitigen.Schnellster Weg, um bestimmte Daten aus Pandas Datenrahmen zu beseitigen

Pandas hat diese große Funktion, wo Sie anrufen:

df.ix['2016-04-22'] 

und alle Zeilen aus diesem Tag ziehen. Aber was, wenn ich alle Zeilen von '2016-04-22' eliminieren möchte?

Ich möchte eine Funktion wie folgt aus:

df.ix[~'2016-04-22'] 

(aber das funktioniert nicht)

Auch was ist, wenn ich möchte eine Liste von Daten beseitigen?

Gerade jetzt, ich habe folgende Lösung:

import numpy as np 
import pandas as pd 
from numpy import random 

###Create a sample data frame 

dates = [pd.Timestamp('2016-04-25 06:48:33'), pd.Timestamp('2016-04-27 15:33:23'), pd.Timestamp('2016-04-23 11:23:41'), pd.Timestamp('2016-04-28 12:08:20'), pd.Timestamp('2016-04-21 15:03:49'), pd.Timestamp('2016-04-23 08:13:42'), pd.Timestamp('2016-04-27 21:18:22'), pd.Timestamp('2016-04-27 18:08:23'), pd.Timestamp('2016-04-27 20:48:22'), pd.Timestamp('2016-04-23 14:08:41'), pd.Timestamp('2016-04-27 02:53:26'), pd.Timestamp('2016-04-25 21:48:31'), pd.Timestamp('2016-04-22 12:13:47'), pd.Timestamp('2016-04-27 01:58:26'), pd.Timestamp('2016-04-24 11:48:37'), pd.Timestamp('2016-04-22 08:38:46'), pd.Timestamp('2016-04-26 13:58:28'), pd.Timestamp('2016-04-24 15:23:36'), pd.Timestamp('2016-04-22 07:53:46'), pd.Timestamp('2016-04-27 23:13:22')] 

values = random.normal(20, 20, 20) 

df = pd.DataFrame(index=dates, data=values, columns ['values']).sort_index() 

### This is the list of dates I want to remove 

removelist = ['2016-04-22', '2016-04-24'] 

grundsätzlich Diese for-Schleife packt den Index für die Daten, die ich entfernen möchten, dann beseitigt es aus dem Index des Hauptdatenrahmen, dann wählt sich positiv auf die verbleibende Daten (dh die guten Daten) aus dem Datenrahmen.

for r in removelist: 
    elimlist = df.ix[r].index.tolist() 
    ind = df.index.tolist() 
    culind = [i for i in ind if i not in elimlist] 
    df = df.ix[culind] 

Gibt es etwas Besseres dort draußen?

Ich habe auch versucht die Indizierung durch die abgerundete Datum + 1 Tag, so etwas wie dieses:

df[~((df['Timestamp'] < r+pd.Timedelta("1 day")) & (df['Timestamp'] > r))] 

Aber das wird wirklich umständlich und (am Ende des Tages) ich noch werde mit werden eine for-Schleife, wenn ich n spezifische Daten löschen muss.

Es muss einen besseren Weg geben! Recht? Könnte sein?

Antwort

1

gleiche Idee wie @Alexander, aber unter Verwendung von Eigenschaften des DatetimeIndex und numpy.in1d:

mask = ~np.in1d(df.index.date, pd.to_datetime(removelist).date) 
df = df.loc[mask, :] 

Timings:

%timeit df.loc[~np.in1d(df.index.date, pd.to_datetime(removelist).date), :] 
1000 loops, best of 3: 1.42 ms per loop 

%timeit df[[d.date() not in pd.to_datetime(removelist) for d in df.index]] 
100 loops, best of 3: 3.25 ms per loop 
+0

Super! Funktioniert perfekt! Vielen Dank für Ihre Antwort! – Reid

-1

Möglicherweise Hilfreiche

df = df.drop(pd.to_datetime('2016-04-22')) 

Dies findet ausdrücklich und entfernt die Zeile mit dem Index gleich pd.to_datetime('2016-04-22') und gibt den Rest. Wenn Sie mehr entfernen möchten, können Sie ein iterables übergeben. Ich habe pd.to_datetime verwendet, weil drop nicht automatisch in datetime konvertiert wird, wenn es wie datetime aussieht und sich so anfühlt wie ix.

Das Problem mit diesem Vorschlag ist, dass wenn ein Element in der übergebenen iterable nicht im Index ist, schlägt es fehl. Es gibt Work arounds, aber zu diesem Zeitpunkt sind @ Alexanders und @ roots Antworten eleganter.

+0

Vielen Dank für Ihre prägnante Antwort! So viel Herzblut. :) Allerdings ist diese bestimmte Lösung nicht hilfreich für mich, weil pd.to_datetime ('2016-04-22') übersetzt in [Timestamp ('2016-04-22 00:00:00')], die ist nicht in meinem Datensatz. – Reid

+0

Ich arbeitete von dem Beispiel, das Sie gaben, das war 'df.ix [~ '2016-04-22']'. 'df.drop (pd.to_datetime ('2016-04-22'))' ist das Äquivalent dessen, was Sie beabsichtigt haben. Die 'pd.to_datetime' ist erforderlich, da' drop' die Konvertierung für Sie nicht ausführt. Ich hatte angenommen, du könntest es zu deinen eigenen Zwecken modifizieren. Wie auch immer, Alexander hat wie immer eine großartige Lösung :-) – piRSquared

+0

Ich höre dich - danke für deine Antwort! Ich frage nach etwas ganz Besonderem, das vielleicht nicht auf dem ursprünglichen Beitrag durchgekommen ist. – Reid

3

Sie können eine boolesche Maske mithilfe eines Listenverständnisses erstellen.

>>> df[[d.date() not in pd.to_datetime(removelist) for d in df.index]] 
         values 
2016-04-21 15:03:49 28.059520 
2016-04-23 08:13:42 -22.376577 
2016-04-23 11:23:41 40.350252 
2016-04-23 14:08:41 14.557856 
2016-04-25 06:48:33 -0.271976 
2016-04-25 21:48:31 20.156240 
2016-04-26 13:58:28 -3.225795 
2016-04-27 01:58:26 51.991293 
2016-04-27 02:53:26 -0.867753 
2016-04-27 15:33:23 31.585201 
2016-04-27 18:08:23 11.639641 
2016-04-27 20:48:22 42.968156 
2016-04-27 21:18:22 27.335995 
2016-04-27 23:13:22 13.120088 
2016-04-28 12:08:20 53.730511 
+0

Große Alternative! Danke Alexander! – Reid

Verwandte Themen