2016-04-05 7 views
0

Ich habe ein Array von über 2 Millionen Datensätze, jeder Datensatz hat eine 10-Minuten-Auflösung Timestamp im Format datetime.datetime, sowie einige andere Werte in anderen Spalten.Filter numpy Array von Datumsangaben nach Häufigkeit des Auftretens

Ich möchte nur die Datensätze, die Zeitstempel haben, die 20 oder öfter im Array auftreten. Was ist der schnellste Weg, dies zu tun? Ich habe viel RAM, also suche ich nach Verarbeitungsgeschwindigkeit.

Ich habe [] .count() in einem Listenverständnis versucht, aber fing an, den Willen zu leben zu verlieren, darauf wartend, es zu beenden. Ich habe auch versucht, numpy.bincount() aber tragischerweise nicht datetime.datetime

Alle Vorschläge würden sehr geschätzt werden. Danke!

+0

'pandas' könnte möglicherweise in O (n) Zeit, so dass ich das Tag hinzugefügt. –

+1

Können Sie ein sehr kleines Beispiel dafür geben, wie Ihr Array aussieht? 3-4 Elemente sollten uns eine gute Idee geben. – Reti43

+0

Verwenden Sie Pandas und machen Sie eine groupBy auf dem Zeitstempel – reptilicus

Antwort

0
  1. Sort Array
  2. Count zusammenhängenden Vorkommen von einmal durchläuft es, & Filter für frequency >= 20

Die Laufzeit ist O (nlog (n)), während Ihre Liste Verständnis war wahrscheinlich O (n ** 2) ... das macht bei 2 Millionen Einträgen einen großen Unterschied.

Je nachdem, wie Ihre Daten strukturiert sind, können Sie möglicherweise nur die benötigten Achsen und Daten aus dem numpy-Array sortieren, das sie enthält.

+0

Gibt es eine schnelle Möglichkeit zum Zählen von Vorkommen, ohne die Daten durchlaufen zu müssen? – WRJ

+0

nein. Sie müssen jeden Eintrag durchgehen, um ihn zu filtern. Wenn die Daten jedoch zuerst sortiert werden, ist das sehr schnell. –

2

Ich bearbeite dies, um die Zeiten mit np.unique basierend auf dem Vorschlag unten zu enthalten. Dies ist bei weitem die beste Lösung

In [10]: import pandas as pd 
     import numpy as np 
     from collections import Counter 

     #create a fake data set 
     dates = pd.date_range("2012-01-01", "2015-01-01", freq="10min") 
     dates = np.random.choice(dates, 2000000, replace=True) 

auf Vorschlag unter der folgenden Basierend wäre der schnellste bei weitem:

In [32]: %%timeit 
     values, counts = np.unique(dates, return_counts=True) 
     filtered_dates = values[counts>20] 
     10 loops, best of 3: 150 ms per loop 

Zähler Verwenden Sie ein Wörterbuch der Zählungen der einzelnen Elemente erstellen und dann wandelt es in ein pd.Series, um die Filterung

In [11]: %%timeit 
     foo = pd.Series(Counter(dates)) 
     filtered_dates = np.array(foo[foo > 20].index) 
     1 loop, best of 3: 12.3 s per loop 

Dies ist zu tun, nicht zu schlecht für ein Array mit 2 Millionen Artikel ist, gegen die folgenden:

In [12]: dates = list(dates) 
     filtered_dates = [e for e in set(dates) if dates.count(e) > 20] 

Ich bin nicht für die Liste Verständnis Version warten werde bis zum Ende ...

1

Eigentlich könnte np.unique versuchen. In numpy v1.9 + unique können einige Extras, wie unique_indices, unique_inverse, unique_counts zurückgegeben werden.

Wenn Sie Pandas verwenden möchten, wäre es ziemlich einfach und wahrscheinlich ziemlich schnell. Sie könnten eine groupby filter verwenden. Etwas wie:

out = df.groupby('timestamp').filter(lambda x: len(x) > 20) 
+0

guter Vorschlag auf der 'np.unique' – johnchase

1

Numpy ist langsamer als Pandas auf diese Art von Operationen, wie np.unique Sorten, während die Maschinen in Pandas nicht brauchen. Weiter ist das viel idiomatischer.

Pandas

In [22]: %%timeit 
    ....: i = Index(dates) 
    ....: i[i.value_counts()>20] 
    ....: 
10 loops, best of 3: 78.2 ms per loop 

In [23]: i = Index(dates) 

In [24]: i[i.value_counts()>20] 
Out[24]: 
DatetimeIndex(['2013-06-16 20:40:00', '2013-05-28 03:00:00', '2013-10-31 19:50:00', '2014-06-20 13:00:00', '2013-07-08 21:40:00', '2012-02-26 17:00:00', '2013-01-02 15:40:00', '2012-08-24 02:00:00', 
       '2014-10-17 08:20:00', '2012-07-27 20:10:00', 
       ... 
       '2014-08-07 05:10:00', '2014-05-21 08:10:00', '2014-03-09 12:50:00', '2013-05-10 02:30:00', '2013-04-15 20:20:00', '2012-06-23 05:20:00', '2012-07-06 16:10:00', '2013-02-14 12:20:00', 
       '2014-10-27 03:10:00', '2013-09-04 12:00:00'], 
       dtype='datetime64[ns]', length=2978, freq=None) 

In [25]: len(i[i.value_counts()>20]) 
Out[25]: 2978 

Numpy (von anderen Lsg)

In [26]: %%timeit 
     values, counts = np.unique(dates, return_counts=True) 
     filtered_dates = values[counts>20] 
    ....: 
10 loops, best of 3: 145 ms per loop 

In [27]: filtered_dates = values[counts>20] 

In [28]: len(filtered_dates) 
Out[28]: 2978 
+0

Vereinbarte, dies ist die beste Lösung so weit, solange Pandas verfügbar ist. – johnchase

0

Danke für alle Ihre Vorschläge.

Ich habe am Ende etwas völlig anderes mit Wörterbüchern gemacht und fand es viel schneller für die Verarbeitung, die ich benötigte.

Ich erstellte ein Wörterbuch mit einem eindeutigen Satz von Zeitstempeln als die Schlüssel und leere Listen als die Werte und dann einmal durch die ungeordnete Liste (oder Array) geloopt und füllte die Wertelisten mit den Werten, die ich zählen wollte.

Danke nochmal!

Verwandte Themen