繁体   English   中英

Matplotlib - 对数图表 - 向图表添加额外文本

[英]Matplotlib - logarithmic chart - adding extra text to chart

我正在尝试基于 pandas dataframe 创建对数图表的可读布局。 我有以下代码:

fig, ax = plt.subplots(figsize=(15, 8))
ax.clear()
ax.barh(mydataframe['Labels'], mydataframe['Values']
plt.xscale('log')
for i, (label, value) in enumerate(zip(mydataframe['Labels'], mydataframe['Values'])):
            ax.text(value + 1, i, f'{value:,.0f}', size=8, ha='left', va='center')
            ax.text(value + 20, i, f'({int(round(extraValue1)):d} -- {extraValue2:,.2f}%)', size=8, ha='left', va='center')

图表布局

如图所示,我的问题是图表上第二个 ax.text 打印的 alignment。 ax.text 的第一行完美地对齐每个条末尾的值。 但是第二个,随着我需要添加的附加信息,alignment 搞砸了并覆盖了以前的值,我们 go 越多到更大的条。 有谁知道我该如何解决这个问题? 我感觉这与使用对数刻度设置的图表有关。 extravalue1 和 2 也是 mydataframe 列的一部分,但为了代码的简单性,我在这里定义了仅主要列的枚举

为了使条形图和文本之间有一个很好的距离,最好使用文本x的精确值,并以一两个空格开始文本。 因此,使用ax.text(value, i, " abc")而不是ax.text(value+20, i, "abc") 要拥有两个文本,只需将它们连接起来并将它们放在一个 go 中。

如果您想要包含多个 colors 的文本,并将它们放置在一起,并有一个适合第一个文本长度的间隙,可以使用偏移框。

要为文本留出更多空间,您可以增加 x 边距,例如ax.margins(x=0.2) 同时,您可以减少 y 边距,这里的默认值有点太大。

import matplotlib.pyplot as plt
from matplotlib.colors import CSS4_COLORS
from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker
import numpy as np

fig, ax = plt.subplots(figsize=(15, 8))
labels = ["".join(np.random.choice(list('abcdef'), 5)) for _ in range(20)]
values = np.sort(10 ** np.random.uniform(1, 5, 20))
ax.barh(labels, values, color=np.random.choice(list(CSS4_COLORS.keys()), 20))
ax.set_xscale('log')
for i, (label, value, extraValue1, extraValue2) in enumerate(
        zip(labels, values, *np.random.randint(100, 1000, (2, 20)))):
    xbox1 = TextArea(f'{value:,.0f}', textprops=dict(color="crimson", size=8, ha='left', va='baseline'))
    xbox2 = TextArea(f'({int(round(extraValue1)):d} -- {extraValue2:,.2f}%)',
                     textprops=dict(color="navy", size=8, ha='left', va='baseline'))
    xbox = HPacker(children=[xbox1, xbox2], align="baseline", pad=0, sep=5)
    anchored_xbox = AnchoredOffsetbox(loc="center left", child=xbox, pad=0.5, frameon=False, bbox_to_anchor=(value, i),
                                      borderpad=0, bbox_transform=ax.transData)
    ax.add_artist(anchored_xbox)
ax.margins(x=0.2, y=0.01)
plt.show()

示例图

即使对于经典(非对数)图表,它也有点混乱,但我用基于值的缩进(如果它是三位数或四位数)进行了修复

if value<1000:
            indent = 80
        else:
            indent = 120
ax.text(value + 20, i, f'({int(round(extraValue1)):d} -- {extraValue2:,.2f}%)', size=8, ha='left', va='center')

日志图表仍然存在问题经典图表

只需将您想要的文本添加到 plot 作为一个字符串不要:

for i, (label, value) in enumerate(zip(mydataframe['Labels'], mydataframe['Values'])):
    text = f'{value:,.0f}\t({int(round(extraValue1)):d} -- {extraValue2:,.2f}%)'
    ax.text(value + 1, i, text, size=8, ha='left', va='center')

或者我错过了什么你不想这样做的原因?

由于您的 x 轴是对数的,因此您希望对文本使用乘法偏移量,而不是加法偏移量。 也就是说,尝试value * 1.2而不是value + 20

fig, ax = plt.subplots(figsize=(15, 8))
ax.clear()
ax.barh(mydataframe['Labels'], mydataframe['Values']
plt.xscale('log')
for i, (label, value) in enumerate(zip(mydataframe['Labels'], mydataframe['Values'])):
            ax.text(value * 1.05, i, f'{value:,.0f}', size=8, ha='left', va='center')
            ax.text(value * 1.2, i, f'({int(round(extraValue1)):d} -- {extraValue2:,.2f}%)', size=8, ha='left', va='center')

请调整1.051.2以满足您的需求。 如果您将两个文本合并为一个,格式可能会看起来更好,但这只是品味。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM