按发生频率过滤numpy日期时间数组

时间:2016-04-05 16:09:46

标签: python datetime numpy pandas filtering

我有一个超过200万条记录的数组,每条记录的datetime.datetime格式都有10分钟的解析时间戳,以及其他列中的其他几个值。

我只想保留在数组中出现20次或更多次时间戳的记录。最快的方法是什么?我有足够的内存,所以我正在寻找处理速度。

我在列表理解中尝试了[] .count(),但开始失去等待它完成的意志。我也试过numpy.bincount(),但不幸的是它不喜欢datetime.datetime

我们非常感谢任何建议。 谢谢!

5 个答案:

答案 0 :(得分:3)

我根据以下建议编辑此内容以使用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万个项目的数组而言,这不是太糟糕了,而不是:

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

我不会等到列表理解版本完成...

答案 1 :(得分:1)

实际上可能会尝试np.unique。在numpy v1.9 + unique中可以返回一些额外内容,例如unique_indicesunique_inverseunique_counts

如果你想使用熊猫,它会非常简单并且可能非常快。您可以使用groupby filter。类似的东西:

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

答案 2 :(得分:1)

Numpy在这些类型的操作上比熊猫慢,因为meta_info_list = [{ 'title': article.find_element_by_xpath('.//article/h2').text, 'share count': article.find_element_by_xpath('.//footer/div/a/span').text, 'points': article.find_element_by_xpath('.//footer/div[2]/div[1]/div[3]').text } for article in article_elements] 排序,而pandas中的机器并不需要。此外,这更加惯用。

熊猫

np.unique

Numpy(来自其他国家)

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

答案 3 :(得分:0)

  1. Sort您的数组
  2. 通过浏览一次计算连续出现次数,&过滤frequency >= 20
  3. 运行时间是O(nlog(n)),而你的列表理解可能是O(n ** 2)......这对200万个条目产生了很大影响。

    根据数据的结构,您可能只能从保存数据的numpy数组中对所需的轴和数据进行排序。

答案 4 :(得分:0)

感谢您的所有建议。

我最终做了一些与词典完全不同的事情,发现它对我所需的处理速度要快得多。

我创建了一个字典,其中包含一组唯一的时间戳作为键,空列表作为值,然后通过无序列表(或数组)循环一次,并使用我想要计算的值填充值列表。

再次感谢!