Matplotlib-标记每个垃圾箱


75

我目前正在使用Matplotlib创建直方图:

在此处输入图片说明

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as pyplot
...
fig = pyplot.figure()
ax = fig.add_subplot(1,1,1,)
n, bins, patches = ax.hist(measurements, bins=50, range=(graph_minimum, graph_maximum), histtype='bar')

#ax.set_xticklabels([n], rotation='vertical')

for patch in patches:
    patch.set_facecolor('r')

pyplot.title('Spam and Ham')
pyplot.xlabel('Time (in seconds)')
pyplot.ylabel('Bits of Ham')
pyplot.savefig(output_filename)

我想使x轴标签更有意义。

首先,这里的x轴刻度似乎仅限于五个刻度。不管我做什么,似乎都无法更改-即使添加更多xticklabel,它也只会使用前五个。我不确定Matplotlib是如何计算的,但是我假设它是根据范围/数据自动计算的?

有什么方法可以提高x-tick标签的分辨率-甚至可以将每个小节/条提高到一个?

(理想情况下,我还希望将秒重新设置为微秒/毫秒,但这又是一个问题)。

其次,我希望每个单独的条都带有标签-带有该垃圾箱中的实际数字以及所有垃圾箱总数的百分比。

最终输出可能看起来像这样:

在此处输入图片说明

Matplotlib是否有可能做到这一点?

干杯,维克多

Answers:


122

当然!要设置刻度,恰好...设置刻度(请参阅matplotlib.pyplot.xticksax.set_xticks)。(此外,您无需手动设置补丁的面色。您只需传递关键字参数即可。)

对于其余的部分,您将需要使用标签做一些花哨的事情,但是matplotlib使其相当容易。

举个例子:

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

data = np.random.randn(82)
fig, ax = plt.subplots()
counts, bins, patches = ax.hist(data, facecolor='yellow', edgecolor='gray')

# Set the ticks to be at the edges of the bins.
ax.set_xticks(bins)
# Set the xaxis's tick labels to be formatted with 1 decimal place...
ax.xaxis.set_major_formatter(FormatStrFormatter('%0.1f'))

# Change the colors of bars at the edges...
twentyfifth, seventyfifth = np.percentile(data, [25, 75])
for patch, rightside, leftside in zip(patches, bins[1:], bins[:-1]):
    if rightside < twentyfifth:
        patch.set_facecolor('green')
    elif leftside > seventyfifth:
        patch.set_facecolor('red')

# Label the raw counts and the percentages below the x-axis...
bin_centers = 0.5 * np.diff(bins) + bins[:-1]
for count, x in zip(counts, bin_centers):
    # Label the raw counts
    ax.annotate(str(count), xy=(x, 0), xycoords=('data', 'axes fraction'),
        xytext=(0, -18), textcoords='offset points', va='top', ha='center')

    # Label the percentages
    percent = '%0.0f%%' % (100 * float(count) / counts.sum())
    ax.annotate(percent, xy=(x, 0), xycoords=('data', 'axes fraction'),
        xytext=(0, -32), textcoords='offset points', va='top', ha='center')


# Give ourselves some more room at the bottom of the plot
plt.subplots_adjust(bottom=0.15)
plt.show()

在此处输入图片说明


啊哈,太棒了=)。另一个注释-最初,我使用“ fig = pyplot.figure(figsize =(32,24),)”和“ ax = fig.add_subplot(1,1,1,)”来设置图形的大小。但是,如果我将第二留置权换成您的“ fig,ax = pyplot.subplots()”,现在似乎忽略了我的figsize吗?知道为什么吗?
victorhooi 2011年

@victorhooi-如果您仅将figsize指定为kwarg,它应该可以工作subplots。例如,fig, ax = plt.subplots(figsize=(32, 34)) 如果不是,也许是错误?subplots1.0作为一种便利功能而添加。
Joe Kington

金斯敦:啊哈,太好了,是的,这行有效=)。你真棒,老兄 我不明白最后一个错误/烦恼-xlabel文本直接位于注释文本的下面-不知道如何抵消它。我尝试了“ ax.xaxis.LABELPAD = 30”,但它似乎忽略了这一点。
victorhooi

@victorhooi-设置刻度线有几种不同的方法,但是最简单的方法是ax.tick_params(axis='x', pad=30)(这有点违反直觉。)希望能有所帮助!
Joe Kington

// @ Joe Kingston:嗯,尝试过,但是它同时移动了x轴标签和刻度线。this这个 大声笑。总之,我认为这应该另外一个问题,所以我在这里转贴它:stackoverflow.com/questions/6406368/...
victorhooi

0

要将SI前缀添加到轴标签,您需要使用QuantiPhy。实际上,在其文档中有一个示例演示了如何执行此操作:MatPlotLib Example

我认为您可以在代码中添加以下内容:

from matplotlib.ticker import FuncFormatter
from quantiphy import Quantity

time_fmtr = FuncFormatter(lambda v, p: Quantity(v, 's').render(prec=2))
ax.xaxis.set_major_formatter(time_fmtr)

0

我想添加到直方图中“密度=真”的图表中的一件事是每个bin的相对频率值,但我找不到能做到这一点的函数。我提出的解决方案如下图所示:

样图图像

功能:

def label_densityHist(ax, n, bins, x=4, y=0.01, r=2, **kwargs):
"""
Add labels,relative value of bin, to each bin in a density histogram .
:param ax: Object axe of matplotlib
        The axis to plot.
:param n: list, array of int, float
        The values of the histogram bins.
:param bins: list, array of int, float
        The edges of the bins.
:param x: int, float
        Related the x position of the bin labels. The higher, the lower the value on the x-axis.
        Default: 4
:param y: int, float
        Related the y position of the bin labels. The higher, the greater the value on the y-axis.
        Default: 0.01
:param r: int
        Number of decimal places.
        Default: 2
:param **kwargs: Text properties in matplotlib
:return: None


Example

import matplotlib.pyplot as plt
import numpy as np

dados = np.random.randn(100)

axe = plt.gca()
n, bins, _ = axe.hist(x=dados, edgecolor='black')
label_densityHist(axe,n, bins)
plt.show()

Example:
import matplotlib.pyplot as plt
import numpy as np


dados = np.random.randn(100)

axe = plt.gca()
n, bins, _ = axe.hist(x=dados, edgecolor='black')
label_densityHist(axe,n, bins, x=6, fontsize='large')
plt.show()


Reference:
[1]https://matplotlib.org/3.1.1/api/text_api.html#matplotlib.text.Text

"""

k = []
# calculate the relative frequency of each bin
for i in range(0,len(n)):
    k.append((bins[i+1]-bins[i])*n[i])

# rounded
k = around(k,r); #print(k)

# plot the label/text to each bin
for i in range(0, len(n)):
    x_pos = (bins[i + 1] - bins[i]) / x + bins[i]
    y_pos = n[i] + (n[i] * y)
    label = str(k[i]) # relative frequency of each bin
    ax.text(x_pos, y_pos, label, kwargs)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.