我有时需要使用matplotlib对离散值进行直方图.在这种情况下,分箱的选择可能是至关重要的:如果您使用10个箱子直方图[0,1,2,3,4,5,6,7,8,9,10],其中一个箱子将有两次和其他人一样多.换句话说,binsize通常应该是离散化大小的倍数.
虽然这个简单的情况本身相对容易处理,但有没有人有一个指向库/函数的指针,可以自动处理这个,包括在浮点数据的情况下,由于FP的离散化大小可能会略有变化四舍五入?
谢谢.
J R*_*ape 22
鉴于您的问题的标题,我将假设离散化大小是不变的.
您可以找到此离散化大小(或至少严格来说,n倍于该大小,因为您的数据中可能没有两个相邻的样本)
np.diff(np.unique(data)).min()
这会在data(np.unique)中找到唯一值,找到then(np.diff)之间的差异.需要唯一性,以便您不会得到零值.然后,您找到最小差异.在离散化常数非常小的情况下可能存在问题 - 我将回过头来看.
接下来 - 您希望您的值位于bin的中间 - 您当前的问题是因为9和10都位于matplotlib自动提供的最后一个bin的边缘,因此您在一个bin中获得两个样本.
所以 - 试试这个:
import matplotlib.pyplot as plt
import numpy as np
data = range(11)
data = np.array(data)
d = np.diff(np.unique(data)).min()
left_of_first_bin = data.min() - float(d)/2
right_of_last_bin = data.max() + float(d)/2
plt.hist(data, np.arange(left_of_first_bin, right_of_last_bin + d, d))
plt.show()
这给出了:

我们可以做一些测试数据集,例如
import random 
data = []
for _ in range(1000):
    data.append(random.randint(1,100))
data = np.array(data)
nasty_d = 1.0 / 597 #Arbitrary smallish discretization
data = data * nasty_d
如果你然后通过上面的数组运行它,看看d代码吐出,你会看到
Run Code Online (Sandbox Code Playgroud)>>> print(nasty_d) 0.0016750418760469012 >>> print(d) 0.00167504187605
所以 - 检测到的值d不是nasty_d创建数据的"实际"值.然而 - 通过将箱子移动一半d来获得中间值的技巧- 除非你的离散化非常小,所以你的下降在浮子的精度范围内,或者你有1000个箱子和检测到的d和"真实的"离散化之间的差异可以构成这样一个点,即其中一个箱"错过"数据点.这是值得注意的事情,但可能不会打击你.
以上的示例图是

对于更复杂的案例,您可能希望查看我发现的这篇博文.本文研究了在开发自己的贝叶斯动态规划方法之前,从(连续/准连续)数据中自动"学习"最佳箱宽度的方法,参考Sturges规则和Freedman和Diaconis规则等多种标准技术.
如果这是您的使用案例 - 问题范围更广,可能不适合Stack Overflow的确定答案,尽管希望链接有所帮助.
Doo*_*opy 18
不完全符合OP的要求,但如果所有值都是整数,则不需要计算箱。
np.unique(d, return_counts=True)返回唯一值列表的元组作为第一个元素,并将它们的计数作为第二个元素。plt.bar(x, height)这可以使用星号运算符直接插入:
import numpy as np
import matplotlib.pyplot as plt
d = [1,1,2,4,4,4,5,6]
plt.bar(*np.unique(d, return_counts=True))
结果如下图:
请注意,从技术上讲,这也适用于浮点数,但结果可能会出乎意料,因为会为每个数字创建一个条形。
Man*_*nez 11
答案可能不及J理查德·斯内普(J Richard Snape)完整,但是我最近学到了一个答案,发现它直观而简单。
import numpy as np
import matplotlib.pyplot as plt
# great seed
np.random.seed(1337)
# how many times will a fair die land on the same number out of 100 trials.
data = np.random.binomial(n=100, p=1/6, size=1000)
# the trick is to set up the bins centered on the integers, i.e.
# -0.5, 0.5, 1,5, 2.5, ... up to max(data) + 1.5. Then you substract -0.5 to
# eliminate the extra bin at the end.
bins = np.arange(0, data.max() + 1.5) - 0.5
# then you plot away
fig, ax = plt.subplots()
_ = ax.hist(data, bins)
ax.set_xticks(bins + 0.5)
原来,大约16/100的投掷次数将是相同的!
| 归档时间: | 
 | 
| 查看次数: | 16492 次 | 
| 最近记录: |