2

假设我有两个列表:

    x1 = [1,2,3,4,5,6,7,8,1,10]
    x2 = [2,4,2,1,1,1,1,1,2,1]

这里,列表的每个索引i都是一个时间点,表示在时间观察到x2[i]的次数(频率)。另请注意,x1[0] = 1 和 x1[8] = 1,总频率为 4 (= x2[0] + x2[8])。x1[i]i

如何有效地将其转换为直方图?简单的方法如下,但这可能效率低下(创建第三个对象并循环)并且会伤害我,因为我有巨大的数据。

import numpy as np
import matplotlib.pyplot as plt

x3 = []
for i in range(10):
    for j in range(x2[i]):
        x3.append(i)

hist, bins = np.histogram(x1,bins = 10)
width = 0.7*(bins[1]-bins[0])
center = (bins[:-1]+bins[1:])/2
plt.bar(center, hist, align = 'center', width = width)
plt.show()
4

3 回答 3

3

最好的方法是使用(doc)weights上的 kwarg ,它还将处理任意 bin 大小和非整数值np.histogram x1

vals, bins = np.histogram(x1, bins=10, weights=x2)

如果您只需要基于整数值进行累积,则可以一次性创建直方图:

new_array = np.zeros(x2.shape)  # or use a list, but I like numpy and you have it
for ind, w in izip(x1, x2):
     # -1 because your events seem to start at 1, not 0
     new_array[ind-1] += w

如果您真的想对列表执行此操作,可以使用列表推导

[_x for val, w in zip(x1, x2) for _x in [val]*w]

返回

[1, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 1, 1, 10]

作为旁注,值得了解如何手动有效地计算直方图:

from __future__ import division
from itertools import izip

num_new_bins = 5
new_min = 0
new_max = 10
re_binned = np.zeros(num_new_bins)
for v, w in izip(x1, x2):
    # figure out what new bin the value should go into
    ind = int(num_new_bins * (v - new_min) / new_max)
    # make sure the value really falls into the new range
    if ind < 0 or ind >= num_new_bins:
        # over flow
        pass
    # add the weighting to the proper bin
    re_binned[ind] += w
于 2013-09-25T13:26:29.040 回答
1

看来您的分箱有问题。 2 的计数应该是 4 。不是吗?这是一个代码。在这里,我们额外创建了一个数组,但它只运行一次,而且是动态的。希望能帮助到你。

import numpy as np
import matplotlib.pyplot as plt

x1 = [1,2,3,4,5,6,7,8,1,10]
x2 = [2,4,2,1,1,1,1,1,2,1]

#your method
x3 = []
for i in range(10):
    for j in range(x2[i]):
        x3.append(i)
plt.subplot(1,2,1)
hist, bins = np.histogram(x1,bins = 10)
width = 0.7*(bins[1]-bins[0])
center = (bins[:-1]+bins[1:])/2
plt.bar(center, hist, align = 'center', width = width)
plt.title("Posted Method")
#plt.show()

#New Method
new_array=np.zeros(len(x1))
for count,p in enumerate(x1):
    new_array[p-1]+=x2[count]
plt.subplot(1,2,2)  
hist, bins = np.histogram(x1,bins = 10)
width = 0.7*(bins[1]-bins[0])
center = (bins[:-1]+bins[1:])/2
plt.bar(center, new_array, align = 'center', width = width)
plt.title("New Method")
plt.show()

这是输出:

在此处输入图像描述

于 2013-09-25T10:30:13.577 回答
-1

一种方法是使用x3 = np.repeat(x1,x2)x3 并制作直方图。

于 2013-09-27T09:26:21.220 回答