2016-04-05 40 views
0

我有超過200萬條記錄的數組,每個記錄都有一個10分鐘的datetime.datetime格式的分辨率時間戳,以及其他列中的其他幾個值。按發生頻率過濾日期時間數組

我只想保留在數組中出現20次或更多時間的記錄。什麼是最快的方法來做到這一點?我有很多內存,所以我正在尋找處理速度。

我已經嘗試[] .count()列表中的理解,但開始失去意願,等待它完成。我也試過numpy.bincount(),但不幸的是它不喜歡datetime.datetime

任何建議將不勝感激。 謝謝!

+0

'熊貓'可能會在O(n)時間做到這一點,所以我添加了標籤。 –

+1

你能舉一個你的數組看起來像什麼樣的小例子嗎? 3-4個元素應該給我們一個足夠好的想法。 – Reti43

+0

使用熊貓做一個組通過時間戳 – reptilicus

回答

0
  1. Sort您的陣列
  2. 計數連續出現通過它去一次,&濾波器frequency >= 20

的運行時間爲O(n日誌(N)),而您的列表理解可能是O( n ** 2)......這在200萬條記錄上有相當大的差異。

根據數據結構的不同,您可能只能從包含它的numpy數組中排序所需的軸和數據。

+0

有沒有一種快速的方法來計算事件而不必循環數據? – WRJ

+0

沒有。你必須通過每個條目來過濾它,但是,如果數據是第一次排序,這是非常快的。 –

2

我在編輯這個以包含使用np.unique的時間根據下面的建議。這是迄今爲止最好的解決辦法

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) 

基於以下下面的建議是最快迄今爲止:

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 

使用計數器,您可以創建每個項目的計數的字典,然後它轉換成一個pd.Series爲了做過濾

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 

這是不是太糟糕了200萬項的數組,VS如下:

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

我不會等待列表理解的版本來完成...

1

其實可以嘗試np.unique。在numpy v1.9 + unique可以返回一些臨時演員,如unique_indices,unique_inverse,unique_counts

如果你想使用熊貓,這將是非常簡單,可能相當快。您可以使用groupby filter。喜歡的東西:

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

'np.unique'的好建議 – johnchase

1

numpy的比對這些類型的操作熊貓慢,因爲np.unique排序,而大熊貓的機器並不需要。而且這更加地道。

熊貓

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的(來自其它溶液)

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

一致認爲,這是迄今爲止最好的解決方案,只要有熊貓可用。 – johnchase

0

感謝您的所有建議。

我最終完成了與字典完全不同的事情,並且發現它對於我所需的處理速度要快得多。

我創建了一個具有唯一一組時間戳作爲鍵和空列表作爲值的字典,然後通過無序列表(或數組)循環一次,並使用我想要計數的值填充值列表。

再次感謝!