用y轴绘制直方图作为百分比(使用FuncFormatter?)

Mat*_*ieu 14 python matplotlib

我有一个数据列表,其中数字在1000到20000之间.

data = [1000, 1000, 5000, 3000, 4000, 16000, 2000]
Run Code Online (Sandbox Code Playgroud)

当我使用hist()函数绘制直方图时,y轴表示bin中值的出现次数.而不是出现次数,我想有出现的百分比.

上面数据列表的直方图

上述情节代码:

f, ax = plt.subplots(1, 1, figsize=(10,5))
ax.hist(data, bins = len(list(set(data))))
Run Code Online (Sandbox Code Playgroud)

我一直在看这篇文章,它描述了一个使用的例子,FuncFormatter但我无法弄清楚如何使它适应我的问题.欢迎一些帮助和指导:)

编辑:主要问题与使用的to_percent(y, position)功能FuncFormatter.y对应于y轴上的一个给定值我猜.我需要将这个值除以我显然无法传递给函数的元素总数...

编辑2:由于使用了全局变量,我不喜欢当前的解决方案:

def to_percent(y, position):
    # Ignore the passed in position. This has the effect of scaling the default
    # tick locations.
    global n

    s = str(round(100 * y / n, 3))
    print (y)

    # The percent symbol needs escaping in latex
    if matplotlib.rcParams['text.usetex'] is True:
        return s + r'$\%$'
    else:
        return s + '%'

def plotting_hist(folder, output):
    global n

    data = list()
    # Do stuff to create data from folder

    n = len(data)
    f, ax = plt.subplots(1, 1, figsize=(10,5))
    ax.hist(data, bins = len(list(set(data))), rwidth = 1)

    formatter = FuncFormatter(to_percent)
    plt.gca().yaxis.set_major_formatter(formatter)

    plt.savefig("{}.png".format(output), dpi=500)
Run Code Online (Sandbox Code Playgroud)

编辑3:方法density = True

在此输入图像描述

实际所需输出(带全局变量的方法):

在此输入图像描述

Imp*_*est 23

其他答案似乎非常复杂.通过对数据进行加权,可以很容易地生成显示比例而不是绝对量的直方图,数据点的数量1/n在哪里n.

然后a PercentFormatter可用于显示比例(例如0.45)百分比(45%).

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import PercentFormatter

data = [1000, 1000, 5000, 3000, 4000, 16000, 2000]

plt.hist(data, weights=np.ones(len(data)) / len(data))

plt.gca().yaxis.set_major_formatter(PercentFormatter(1))
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在这里,我们看到7个值中的3个在第一个bin中,即3/7 = 43%.

  • 要消除对 numpy 的依赖,可以将 `weights=np.ones(len(data)) / len(data)` 替换为 `weights = [1/len(data)] * len(data)`。 (2认同)

小智 14

只需将密度设置为 true,权重就会隐式标准化。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import PercentFormatter

data = [1000, 1000, 5000, 3000, 4000, 16000, 2000]

plt.hist(data, density=True)

plt.gca().yaxis.set_major_formatter(PercentFormatter(1))
plt.show()
Run Code Online (Sandbox Code Playgroud)

  • `密度= True`没有按照OP的要求给出“出现的百分比”。大多数用户不会寻找“密度=真”(谷歌它看看为什么)。 (6认同)

Man*_*yer 9

我认为最简单的方法是使用seaborn,它是matplotlib 上的一个层。请注意,您仍然可以使用plt.subplots()figsize()axfig来自定义绘图。

import seaborn as sns
Run Code Online (Sandbox Code Playgroud)

并使用以下代码:

sns.displot(data, stat='probability'))
Run Code Online (Sandbox Code Playgroud)

此外,sns.displot具有如此多的参数,可以非常轻松地绘制非常复杂且信息丰富的图表。它们可以在这里找到:displot 文档


Dav*_*idG 7

您可以自己计算百分比,然后将它们绘制为条形图。这需要您使用numpy.histogram(无论如何,matplotlib 使用“幕后”)。然后,您可以调整 y 刻度标签:

import matplotlib.pyplot as plt
import numpy as np

f, ax = plt.subplots(1, 1, figsize=(10,5))
data = [1000, 1000, 5000, 3000, 4000, 16000, 2000]

heights, bins = np.histogram(data, bins = len(list(set(data))))

percent = [i/sum(heights)*100 for i in heights]

ax.bar(bins[:-1], percent, width=2500, align="edge")
vals = ax.get_yticks()
ax.set_yticklabels(['%1.2f%%' %i for i in vals])

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明