在matplotlib条形图上添加值标签

问题描述 投票:74回答:4

我被困在感觉上应该相对容易的东西上。我在下面提供的代码是基于我正在从事的一个较大项目的示例。我认为没有理由发布所有详细信息,因此请原样接受我带来的数据结构。

[基本上,我正在创建一个条形图,我可以弄清楚如何在条形图上(在条形图的中心或上方)添加值标签。一直在网上查看示例,但是在我自己的代码上实现没有成功。我相信解决方案是使用“文本”或“注释”,但是我:a)不知道使用哪个(通常来说,还没有弄清楚何时使用哪个)。b)看不到要显示值标签。感谢您的帮助,下面是我的代码。预先感谢!

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
pd.set_option('display.mpl_style', 'default') 
%matplotlib inline

# Bring some raw data.
frequencies = [6, 16, 75, 160, 244, 260, 145, 73, 16, 4, 1]

# In my original code I create a series and run on that, 
# so for consistency I create a series from the list.
freq_series = pd.Series.from_array(frequencies)

x_labels = [108300.0, 110540.0, 112780.0, 115020.0, 117260.0, 119500.0, 
            121740.0, 123980.0, 126220.0, 128460.0, 130700.0]

# Plot the figure.
plt.figure(figsize=(12, 8))
fig = freq_series.plot(kind='bar')
fig.set_title('Amount Frequency')
fig.set_xlabel('Amount ($)')
fig.set_ylabel('Frequency')
fig.set_xticklabels(x_labels)
python python-2.7 pandas matplotlib data-visualization
4个回答
101
投票

首先freq_series.plot返回一个轴not一个数字,以便使我的回答更加清楚,我已更改了给定的代码,将其称为ax而不是fig,以便与其他代码示例。

您可以从ax.patches成员那里获得图中绘制的柱线的列表。然后,您可以使用this matplotlib gallery example中演示的技术通过matplotlib方法添加标签。

ax.text

这将产生一个标记的图,看起来像:

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS8wUk1hei5wbmcifQ==” alt =“在此处输入图像描述”>


38
投票

基于ax.text中提到的功能,我发现了一种非常普遍适用的将标签放置在条形图上的解决方案。

不幸的是,其他解决方案在许多情况下不起作用,因为标签和条形之间的间距是import numpy as np import pandas as pd import matplotlib.pyplot as plt # Bring some raw data. frequencies = [6, 16, 75, 160, 244, 260, 145, 73, 16, 4, 1] # In my original code I create a series and run on that, # so for consistency I create a series from the list. freq_series = pd.Series.from_array(frequencies) x_labels = [108300.0, 110540.0, 112780.0, 115020.0, 117260.0, 119500.0, 121740.0, 123980.0, 126220.0, 128460.0, 130700.0] # Plot the figure. plt.figure(figsize=(12, 8)) ax = freq_series.plot(kind='bar') ax.set_title('Amount Frequency') ax.set_xlabel('Amount ($)') ax.set_ylabel('Frequency') ax.set_xticklabels(x_labels) rects = ax.patches # Make some labels. labels = ["label%d" % i for i in xrange(len(rects))] for rect, label in zip(rects, labels): height = rect.get_height() ax.text(rect.get_x() + rect.get_width() / 2, height + 5, label, ha='center', va='bottom') this answer to another question。前者仅适用于狭窄范围的值,而后者在一个绘图中给出的间距不一致。对数轴都不能很好地工作。

我提出的解决方案与比例无关(即,无论大小),甚至正确地为负值和对数比例放置标签,因为它使用可视单位given in absolute units of the bars进行偏移。

我添加了一个负数以展示这种情况下标签的正确放置。

每个条形的高度值用作其标签。其他标签可以通过scaled by the height of the bar轻松使用。

points

编辑:我已经提取了一个功能中的相关功能,如Simon's for rect, label in zip(rects, labels) snippet所建议。

这将产生以下输出:

for rect, label in zip(rects, labels)

并且使用对数标度(以及对输入数据的一些调整以显示对数标度),这是结果:

import numpy as np import pandas as pd import matplotlib.pyplot as plt # Bring some raw data. frequencies = [6, -16, 75, 160, 244, 260, 145, 73, 16, 4, 1] # In my original code I create a series and run on that, # so for consistency I create a series from the list. freq_series = pd.Series.from_array(frequencies) x_labels = [108300.0, 110540.0, 112780.0, 115020.0, 117260.0, 119500.0, 121740.0, 123980.0, 126220.0, 128460.0, 130700.0] # Plot the figure. plt.figure(figsize=(12, 8)) ax = freq_series.plot(kind='bar') ax.set_title('Amount Frequency') ax.set_xlabel('Amount ($)') ax.set_ylabel('Frequency') ax.set_xticklabels(x_labels) def add_value_labels(ax, spacing=5): """Add labels to the end of each bar in a bar chart. Arguments: ax (matplotlib.axes.Axes): The matplotlib object containing the axes of the plot to annotate. spacing (int): The distance between the labels and the bars. """ # For each bar: Place a label for rect in ax.patches: # Get X and Y placement of label from rect. y_value = rect.get_height() x_value = rect.get_x() + rect.get_width() / 2 # Number of points between bar and label. Change to your liking. space = spacing # Vertical alignment for positive values va = 'bottom' # If value of bar is negative: Place label below bar if y_value < 0: # Invert space to place label below space *= -1 # Vertically align label at top va = 'top' # Use Y value as label and format number with one decimal place label = "{:.1f}".format(y_value) # Create annotation ax.annotate( label, # Use `label` as label (x_value, y_value), # Place label at end of the bar xytext=(0, space), # Vertically shift label by `space` textcoords="offset points", # Interpret `xytext` as offset in points ha='center', # Horizontally center label va=va) # Vertically align label differently for # positive and negative values. # Call the function above. All the magic happens there. add_value_labels(ax) plt.savefig("image.png")


22
投票

基于以上(很好!)的答案,我们还可以通过一些调整就可以制作出水平条形图:

barnhillec

“带注释的水平条形图”“>


0
投票

如果只想在条形上方添加数据点,则可以轻松地通过以下方式进行:

© www.soinside.com 2019 - 2024. All rights reserved.