这本身不是一个答案,但由于使用 numpy 而不是 python 的 for 循环,它可能会更快。
首先,您要执行一些分箱:
>> bins = np.digitize(t, z) - 1 # minus 1 just to align our shapes
array([5, 5, 3, 1, 0, 2, 0, 5, 6, 4, 2, 0, 4, 5, 2])
这会告诉您每个值在哪个 bin 中。接下来,按顺序定义您的模式:
>> patterns = np.array([
[0,0,0,0,0],
[0,0,0,0,1],
[0,0,0,1,0],
[0,0,0,1,1],
[0,0,1,0,0],
[0,0,1,0,1],
[0,0,1,1,0],
])
现在对于一些 numpy 魔术,而不是追加/扩展,创建一个充满零的数组(这应该几乎总是更快)。该数组将具有 shape (len(t), len(z)-1)
。使用这个 SO answer,我们还将进行 one-hot 编码:
>> inds = np.zeros((len(t), len(z)-1))
>> inds[np.arange(len(t)), bins] = 1
>> inds
array([[0., 0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 1., 0.],
[0., 0., 0., 1., 0., 0., 0.],
.....,
[0., 0., 0., 0., 0., 1., 0.],
[0., 0., 1., 0., 0., 0., 0.]])
最后,我们只需要一个矩阵乘法
>> inds @ patterns
array([[0., 0., 1., 0., 1.],
[0., 0., 1., 0., 1.],
[0., 0., 0., 1., 1.],
....
[0., 0., 1., 0., 1.],
[0., 0., 0., 1., 0.]])
我没有进行质量时序测试,但从我的小实验来看,这是我的结果:
您的循环:每个循环 17.7 µs ± 160 ns(平均 ± 7 次运行的标准偏差,每个循环 100000 个循环) 我的实现:每个循环 8.49 µs ± 125 ns(平均 ± 7 次运行的标准偏差,每个循环 100000 个循环)
这可能会或可能不会很好地扩展到更大的数据集。希望这可以帮助 :)
编辑:按照Alexander Lopatin 的回答,我很感兴趣地看到我的方法明显变慢了。经过进一步调查,我得出的一个结论是,它numpy
的函数有一些显着的开销,这对于少数几个值来说并不是一个便宜的价格t
。对于较大的列表,numpy 开销微不足道,但性能提升却不是:
timings = {
10: [7.79, 24.1, 21.7],
16: [10.7, 29.9, 22.9],
24: [14.6, 40.5, 23.4],
33: [19.1, 48.6, 23.4],
38: [21.9, 55.9, 23.9],
47: [26.7, 66.2, 24.1],
61: [33, 79.5, 24.7],
75: [40.8, 92.6, 25.8],
89: [47.6, 108, 26.2],
118: [60.1, 136, 27.4],
236: [118, 264, 33.1],
472: [236, 495, 40.9],
1000: [657, 922, 52],
10000: [6530, 9090, 329]
}
飞涨: