Numpy 使用matplotlib的离散值直方图

Numpy 使用matplotlib的离散值直方图,numpy,matplotlib,Numpy,Matplotlib,我有时不得不使用matplotlib对离散值进行直方图分析。在这种情况下,装箱的选择可能是至关重要的:如果使用10个箱子对柱状图[0、1、2、3、4、5、6、7、8、9、10]进行分类,其中一个箱子的计数将是其他箱子的两倍。换句话说,binsize通常应该是离散化大小的倍数 虽然这种简单的情况相对容易自己处理,但是否有人拥有指向自动处理此问题的库/函数的指针,包括浮点数据,其中离散化大小可能会因FP舍入而略有变化 谢谢。鉴于您问题的标题,我将假设离散化大小是恒定的 您可以找到该离散化大小(或者至

我有时不得不使用matplotlib对离散值进行直方图分析。在这种情况下,装箱的选择可能是至关重要的:如果使用10个箱子对柱状图[0、1、2、3、4、5、6、7、8、9、10]进行分类,其中一个箱子的计数将是其他箱子的两倍。换句话说,binsize通常应该是离散化大小的倍数

虽然这种简单的情况相对容易自己处理,但是否有人拥有指向自动处理此问题的库/函数的指针,包括浮点数据,其中离散化大小可能会因FP舍入而略有变化


谢谢。

鉴于您问题的标题,我将假设离散化大小是恒定的

您可以找到该离散化大小(或者至少严格地说,n乘以该大小,因为您的数据中可能没有两个相邻的样本)

这将查找数据中的唯一值(
np.unique
),查找它们之间的差异(
np.diff
)。需要唯一值,以便不获取零值。然后找到最小的差异。在离散化常数非常小的情况下,这可能会有问题——我会回到那个问题上来

下一步-你希望你的值在bin的中间-你当前的问题是因为9和10都在MattTLIB自动提供的最后一个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
,您将看到

因此,
d
的检测值不是创建数据时使用的
d
的“真实”值。但是,通过将代码框移到“代码”>“d>代码”的一半,以获得中间值,这不应该是<强> >除非您的离散化非常小,所以在一个浮点<强>或<>强>的精度范围内,您有100000个容器和检测到的<代码> d>代码>和“真实”之间的差异。离散化可能会导致其中一个箱子“遗漏”数据点。这是需要注意的,但可能不会影响你

上面的示例图如下所示


非均匀离散化/最合适的箱子。。。 对于更复杂的情况,您可能希望查看。本文着眼于从(连续/准连续)数据中自动“学习”最佳仓位宽度的方法,参考多种标准技术,例如在开发自己的贝叶斯动态规划方法之前


如果这是您的使用案例-问题范围更广,可能不适用于堆栈溢出的最终答案,尽管希望链接会有所帮助。

可能是一个不太完整的答案,但我最近学到了一个,而且我觉得直观且简单的答案

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次投掷将是相同的数字

另一个版本,只需少量代码即可处理简单案例!这次使用和:

给我:


这看起来非常可读

不完全是OP要求的,但如果所有值都是整数,则不需要计算箱子

将唯一值列表的元组作为第一个元素返回,并将其计数作为第二个元素返回。可使用star运算符直接插入:

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))
这将导致以下绘图:


请注意,这在技术上也适用于浮点数,但是结果可能会出乎意料,因为每个数字都会创建一个条。

Nice,我没有意识到移动半个位可以解决我所担心的大多数问题(事实上,我所说的是统一离散化,而不是我所知道的Freedman Diaconis类型规则)。我认为当你说“那么-检测到的d值不是d的“真实”值”时,代码中有一个输入错误。谢谢。这个输入错误很好-我现在已经清理了。注意:有用的直方图选项:
plt.hist(x,箱子=箱子,密度=真,color=“绿色”,ec=“黑色”
其中
ec
代表“边缘颜色”。
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)
import numpy as np
import matplotlib.pyplot as plt

# same seed/data as Manuel Martinez to make plot easy to compare
np.random.seed(1337)
data = np.random.binomial(100, 1/6, 1000)

values, counts = np.unique(data, return_counts=True)

plt.vlines(values, 0, counts, color='C0', lw=4)

# optionally set y-axis up nicely
plt.ylim(0, max(counts) * 1.06)
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))