我有一个2D的numpy数组,由ca. 15'000'000数据点。每个数据点都有一个时间戳和一个整数值(介于40和200之间)。我必须创建数据点分布的直方图(16个区间:40-49,50-59等),按年份,按当前年份的月份,按当前年份的星期,以及当前月份的日期排序。
现在,我想知道实现这一目标的最有效方法是什么。鉴于阵列的大小,性能是一个显着的考虑因素。我正在考虑嵌套的“for”循环,按年,按月等分解阵列。但我正在阅读numpy数组具有高内存效率,并且有各种各样的技巧可以快速处理。所以我想知道是否有更快的方法来做到这一点。你可能已经意识到,我是一名业余程序员(“真实生活”中的分子生物学家),我的问题可能相当天真。
答案 0 :(得分:2)
首先,在不考虑日期的情况下填写您的16个箱子。 然后,按日期对每个bin中的元素进行排序。 现在,您可以使用二进制搜索在每个bin中有效地定位给定的年/月/周。
答案 1 :(得分:2)
为了做到这一点,numpy
,numpy.bincount
中有一个功能。它非常快。它是如此之快,你可以为每个整数(161个箱子)和一天(可能30000个不同的天?)创建一个箱子,从而产生几百万箱。
程序:
np.bincount
现在您拥有了分箱数据,然后可以将其聚集到时间维度中所需的任何分档中。
在不知道输入数据的形式的情况下,整数bin计算代码可能是这样的:
# let us assume we have the data as:
# timestamps: 64-bit integer (seconds since something)
# values: 8-bit unsigned integer with integers between 40 and 200
# find the first day in the sample
first_day = np.min(timestamps) / 87600
# we intend to do this but fast:
indices = (timestamps / 87600 - first_day) * 17 + ((values - 40) / 10)
# get the bincount vector
b = np.bincount(indices)
# calculate the number of days in the sample
no_days = (len(b) + 16) / 17
# reshape b
b.resize((no_days, 17))
应该注意b
中的第一天和最后一天取决于数据。在测试中,大部分时间用于计算指数(使用i7处理器大约400毫秒)。如果需要减少,可以使用numexpr
模块在大约100 ms内完成。但是,实际的实现在很大程度上取决于时间戳的形式;有些更快计算,有些更慢。
但是,如果需要的数据达到每日水平,我怀疑是否有任何其他分箱方法会更快。
如果你想对(一年一次,一周一周等)或其他一些分类方法有不同的观点,我对你的问题并不十分了解。在任何情况下归结为将相关行汇总在一起。
答案 2 :(得分:1)
这是一个解决方案,使用以下链接中的group_by功能: http://pastebin.com/c5WLWPbp
import numpy as np
dates = np.arange('2004-02', '2005-05', dtype='datetime64[D]')
np.random.shuffle(dates)
values = np.random.randint(40,200, len(dates))
years = np.array(dates, dtype='datetime64[Y]')
months = np.array(dates, dtype='datetime64[M]')
weeks = np.array(dates, dtype='datetime64[W]')
from grouping import group_by
bins = np.linspace(40,200,17)
for m, g in zip(group_by(months)(values)):
print m
print np.histogram(g, bins=bins)[0]
或者,你可以看一下pandas包,它也可能是这个问题的优雅解决方案。