matplotlib/pandas 中是不是有参数将直方图的 Y 轴作为百分比?

Posted

技术标签:

【中文标题】matplotlib/pandas 中是不是有参数将直方图的 Y 轴作为百分比?【英文标题】:Is there a parameter in matplotlib/pandas to have the Y axis of a histogram as percentage?matplotlib/pandas 中是否有参数将直方图的 Y 轴作为百分比? 【发布时间】:2013-07-26 07:02:09 【问题描述】:

我想比较两个直方图,让 Y 轴显示每列占整个数据集大小的百分比,而不是绝对值。那可能吗?我正在使用熊猫和 matplotlib。 谢谢

【问题讨论】:

normed=True 添加到您的plt.hist() 谢谢!由于某种原因,该选项未记录在 pandas.pydata.org/pandas-docs/dev/generated/… 中。但是,我在 Y 轴上得到的值等于且大于 1(例如 1.4)。知道这怎么可能吗?我的直觉是,一旦标准化,值应该在 0-1 之间。 第二个问题! 不推荐使用“规范”kwarg,并已被“密度”取代 【参考方案1】:

density=Truenormed=True for matplotlib < 2.2.0)返回一个直方图,其中np.sum(pdf * np.diff(bins)) 等于 1。如果您希望直方图的总和为 1,您可以使用 Numpy 的 histogram() 并自己标准化结果.

x = np.random.randn(30)

fig, ax = plt.subplots(1,2, figsize=(10,4))

ax[0].hist(x, density=True, color='grey')

hist, bins = np.histogram(x)
ax[1].bar(bins[:-1], hist.astype(np.float32) / hist.sum(), width=(bins[1]-bins[0]), color='grey')

ax[0].set_title('normed=True')
ax[1].set_title('hist = hist / hist.sum()')

顺便说一句:左侧绘图的第一个 bin 出现奇怪的绘图故障。

【讨论】:

太棒了(也是如何使用子图的一个很好的例子) 你能解释一下为什么熊猫会这样吗?我有点困惑。我想大多数人会选择 sum =1 的方式。 normed 在 matplotlib 2.2.0 版中已弃用;请改用 density 关键字参数。 matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html 参数density=True 不会按总计数对直方图进行归一化。也就是说,条形的高度之和不会为 1(而是当density=True 时,高度*宽度之和为 1,这不是人们说规范化直方图时的想法)。要标准化直方图,请参阅此github.com/matplotlib/matplotlib/issues/10398/… 或此***.com/a/16399202 有趣的是normed=True 已被弃用。这是一个直观且有用的参数;我以前经常使用它。【参考方案2】:

Pandas 绘图可以接受来自相应 matplotlib 函数的任何额外关键字参数。因此,为了从这里其他人的 cmets 中获得完整性,这就是人们将如何做到的:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(100,2), columns=list('AB'))

df.hist(density=1)

另外,为了直接比较,这也可能是一个好方法:

df.plot(kind='hist', density=1, bins=20, stacked=False, alpha=.5)

【讨论】:

【参考方案3】:

看起来像@CarstenKönig found the right way:

df.hist(bins=20, weights=np.ones_like(df[df.columns[0]]) * 100. / len(df))

【讨论】:

我认为100 放错了位置。正确的版本是df.hist(bins=20, weights=np.ones_like(df[df.columns[0]]) * 100. / len(df)),以防你想到的是从 0 到 100 的数字。 确实如此。接得好!已更正。【参考方案4】:

我知道这个答案是 6 年后的事,但对于任何使用密度 = True(normed = True 的替代品)的人来说,这并不是你想做的。它将对整个分布进行归一化,使箱的面积为 1。因此,如果您有更多宽度 1(y 轴)。如果您想将直方图绑定到 [0;1],则必须自己计算。

【讨论】:

这也是我发现的 或者可能是df["col"].plot.hist(ax=ax, cumulative=true, weights=list(100*numpy.ones_like(df.index)/len(df.index)))ax.yaxis.set_major_formatter(plt.FuncFormatter(':.0f%'.format)) 之类的东西。不是在公园里散步,但可以工作。【参考方案5】:

您可以使用 np.ones_like() 来简化权重:

df["ColumnName"].plot.hist(weights = np.ones_like(df.index) / len(df.index))
np.ones_like() 可以使用 df.index 结构 len(df.index) 对于大型 DataFrame 更快

【讨论】:

由于某种原因,该命令给了我错误ValueError: weights should have the same shape as x (matplotlib 3.0.3)。对我有用的命令是df["ColumnName"].plot.hist(weights = list(np.ones_like(df.index) / len(df.index)))【参考方案6】:

我知道这是一个老问题,但它在某些搜索中显示在顶部,所以我认为从 2021 年开始,seaborn 将是一个简单的方法。

你可以这样做:

import seaborn as sns
sns.histplot(df,stat="probability")

【讨论】:

以上是关于matplotlib/pandas 中是不是有参数将直方图的 Y 轴作为百分比?的主要内容,如果未能解决你的问题,请参考以下文章

数据可视化实例: 带线性回归最佳拟合线的散点图(matplotlib,pandas)

绘制/计算指数曲线的问题(python、matplotlib、pandas)

如何使用 Matplotlib、pandas 和 sklearn 创建线性回归图?

Matplotlib:pandas MultiIndex DataFrame 的自定义代码

数据可视化代码实例(Matplotlib+Pandas)

根据星期时间统计日期总量,绘制matplotlib,pandas,Python