如何在条形图上显示自定义值

2025-02-13 08:36:00
admin
原创
26
摘要:问题描述:我想了解如何在 Seaborn 中做两件事:使用条形图显示数据框中存在但不在图表中的值。我希望在绘制数据框中一个字段的值的同时显示另一个字段的值。例如,下面,我正在绘制“tip”,但我想将值置于'total_bill'每个条形图上方的中心位置(即星期五上方为 325.88,星期六上方为 1778.4...

问题描述:

我想了解如何在 Seaborn 中做两件事:使用条形图显示数据框中存在但不在图表中的值。

  1. 我希望在绘制数据框中一个字段的值的同时显示另一个字段的值。例如,下面,我正在绘制“tip”,但我想将值置于'total_bill'每个条形图上方的中心位置(即星期五上方为 325.88,星期六上方为 1778.40,等等)。

  2. 有没有办法缩放条形图的颜色,使最低值具有'total_bill'最浅的颜色(在本例中为星期五),最高值具有'total_bill'最深的颜色?显然,我在缩放时会坚持使用一种颜色(即蓝色)。

虽然我看到其他人认为这是另一个(或两个)问题的重复,但我忽略了如何使用图表中不存在的值作为标签或阴影的基础。我怎么说呢,使用 total_bill 作为基础。很抱歉,但我无法根据这些答案找到答案。

从以下代码开始,

import pandas as pd
import seaborn as sns
%matplotlib inline

df = pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/1st-edition/ch08/tips.csv", sep=',')
groupedvalues = df.groupby('day').sum().reset_index()
g = sns.barplot(x='day', y='tip', data=groupedvalues)

我得到以下结果:

在此处输入图片描述

临时解决方案:

for index, row in groupedvalues.iterrows():
    g.text(row.name, row.tip, round(row.total_bill, 2), color='black', ha="center")

在此处输入图片描述

阴影上,使用下面的示例,我尝试了以下操作:

import pandas as pd
import seaborn as sns
%matplotlib inline

df = pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/1st-edition/ch08/tips.csv", sep=',')
groupedvalues = df.groupby('day').sum().reset_index()

pal = sns.color_palette("Greens_d", len(data))
rank = groupedvalues.argsort().argsort()
g = sns.barplot(x='day', y='tip', data=groupedvalues)

for index, row in groupedvalues.iterrows():
    g.text(row.name, row.tip, round(row.total_bill, 2), color='black', ha="center")

但这给了我以下错误:

AttributeError:'DataFrame'对象没有属性'argsort'

所以我尝试进行修改:

import pandas as pd
import seaborn as sns
%matplotlib inline

df = pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/1st-edition/ch08/tips.csv", sep=',')
groupedvalues = df.groupby('day').sum().reset_index()

pal = sns.color_palette("Greens_d", len(data))
rank = groupedvalues['total_bill'].rank(ascending=True)
g = sns.barplot(x='day', y='tip', data=groupedvalues, palette=np.array(pal[::-1])[rank])

这让我

IndexError:索引 4 超出了大小为 4 的轴 0 的范围


解决方案 1:

matplotlib 3.4.0 中的新功能

  • 现在有一个内置功能Axes.bar_label可以自动标记栏容器:

ax = sns.barplot(x='day', y='tip', data=groupedvalues)
ax.bar_label(ax.containers[0]) # only 1 container needed unless using `hue`

seaborn 条形图标记

  • 对于自定义标签(例如,tip带有值的条形图total_bill),请使用以下labels参数:

ax = sns.barplot(x='day', y='tip', data=groupedvalues)
ax.bar_label(ax.containers[0], labels=groupedvalues['total_bill'])
#                              ----------------------------------

seaborn 条形图自定义值

  • 对于多组条形图(即带有hue),将会有多个需要迭代的条形容器:

ax = sns.barplot(x='day', y='tip', hue='sex', data=df)
for container in ax.containers:
    ax.bar_label(container)

seaborn 分组条形图标记

更多详细信息:

  • 如何标记百分比计数(fmt参数)

  • 如何旋转标签(rotation参数)

  • 如何垂直居中标签(label_type参数)

  • 如何给标签添加间距(padding参数)


颜色排序版本

有没有办法缩放条形图的颜色,使最低值具有total_bill最浅的颜色(在本例中为星期五),最高值具有total_bill最深的颜色?

  1. 找出每个值的等级total_bill

* 使用`Series.sort_values`:


ranks = groupedvalues.total_bill.sort_values().index
# Int64Index([1, 0, 3, 2], dtype='int64')
* `Series.rank`或者通过链接压缩 Ernest 的版本`Series.sub`:


ranks = groupedvalues.total_bill.rank().sub(1).astype(int).array
# [1, 0, 3, 2]
  1. 然后使用以下命令重新索引调色板ranks

palette = sns.color_palette('Blues_d', len(ranks))
ax = sns.barplot(x='day', y='tip', palette=np.array(palette)[ranks], data=groupedvalues)

seaborn 条形图颜色排序

解决方案 2:

这适用于单个 ax 或 ax 矩阵(子图):

from matplotlib import pyplot as plt
import numpy as np

def show_values_on_bars(axs):
    def _show_on_single_plot(ax):
        for p in ax.patches:
            _x = p.get_x() + p.get_width() / 2
            _y = p.get_y() + p.get_height()
            value = '{:.2f}'.format(p.get_height())
            ax.text(_x, _y, value, ha="center")

    if isinstance(axs, np.ndarray):
        for idx, ax in np.ndenumerate(axs):
            _show_on_single_plot(ax)
    else:
        _show_on_single_plot(axs)

fig, ax = plt.subplots(1, 2)
show_values_on_bars(ax)

解决方案 3:

坚持使用来自更改 seaborn 条形图中的颜色比例的解决方案,该解决方案用于argsort确定条形颜色的顺序。在链接的问题中,argsort应用于一个Series对象,而在这里您有一个。选择要应用DataFrame的一列。DataFrame`argsort`

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

df = sns.load_dataset('tips')
groupedvalues = df.groupby('day').sum().reset_index()

pal = sns.color_palette('Greens_d', len(groupedvalues))
rank = groupedvalues['total_bill'].argsort().argsort() 
g = sns.barplot(x='day', y='tip', data=groupedvalues, palette=np.array(pal[::-1])[rank])

for index, row in groupedvalues.iterrows():
    g.text(row.name, row.tip, round(row.total_bill, 2), color='black', ha='center')
    
plt.show()

在此处输入图片描述


第二次尝试也很好,唯一的问题是 返回的排名从 开始rank()1而不是0。因此必须1从数组中减去。对于索引,我们需要整数值,因此将其转换为int

rank = groupedvalues['total_bill'].rank(ascending=True).values
rank = (rank-1).astype(int)

  • 从 中matplotlib 3.4.0,有.bar_label,它有一个label用于自定义标签的参数。

    • 其他答案使用.bar_label没有用自定义标签labels=

    • 请参阅 2021 年 5 月 16 日的这个答案.bar_label,以获得包含文档和示例链接的详细解释。

  1. day列将下载为category Dtype,这样可以保持一周中各天的顺序。这还可以确保 x 轴上的条形图和 中的值的绘制顺序tb

    • .bar_label从左到右添加标签,因此中的值的tb顺序与条形图的顺序相同。

    • 如果使用非分类列,pd.Categorical则可以在该列上使用它来设置顺序。

  • 在 中sns.barplotestimator=sum指定为和tip。默认值为mean

df = sns.load_dataset("tips")

# sum total_bill by day
tb = df.groupby('day').total_bill.sum()

# get the colors in blues as requested
pal = sns.color_palette("Blues_r", len(tb))

# rank the total_bill sums
rank = tb.argsort()

# plot
fig, ax = plt.subplots(figsize=(8, 6))
sns.barplot(x='day', y='tip', data=df, palette=np.array(pal[::-1])[rank], estimator=sum, ci=False, ax=ax)

# 1. add labels using bar_label with custom labels from tb
ax.bar_label(ax.containers[0], labels=tb, padding=3)

# pad the spacing between the number and the edge of the figure
ax.margins(y=0.1)

plt.show()

在此处输入图片描述

解决方案 4:

如果有人对标记水平条形图感兴趣,我修改了Sharon 的答案如下:

def show_values_on_bars(axs, h_v="v", space=0.4):
    def _show_on_single_plot(ax):
        if h_v == "v":
            for p in ax.patches:
                _x = p.get_x() + p.get_width() / 2
                _y = p.get_y() + p.get_height()
                value = int(p.get_height())
                ax.text(_x, _y, value, ha="center") 
        elif h_v == "h":
            for p in ax.patches:
                _x = p.get_x() + p.get_width() + float(space)
                _y = p.get_y() + p.get_height()
                value = int(p.get_width())
                ax.text(_x, _y, value, ha="left")

    if isinstance(axs, np.ndarray):
        for idx, ax in np.ndenumerate(axs):
            _show_on_single_plot(ax)
    else:
        _show_on_single_plot(axs)

两个参数解释:

h_v- 条形图是水平的还是垂直的。"h"表示水平条形图,"v"表示垂直条形图。

space- 值文本和栏顶部边缘之间的空间。仅适用于水平模式。

例子:

show_values_on_bars(sns_t, "h", 0.3)

在此处输入图片描述

解决方案 5:

plt.figure(figsize=(15, 10))
graph = sns.barplot(x='name_column_x_axis', y="name_column_x_axis", data=dataframe_name, color="salmon")
for p in graph.patches:
    graph.annotate('{:.0f}'.format(p.get_height()),
                   (p.get_x() + 0.3, p.get_height()),
                   ha='center',
                   va='bottom',
                   color='black')

解决方案 6:

import seaborn as sns

fig = plt.figure(figsize = (12, 8))
ax = plt.subplot(111)

ax = sns.barplot(x="Knowledge_type", y="Percentage", hue="Distance", data=knowledge)

for p in ax.patches:
    ax.annotate(format(p.get_height(), '.2f'), (p.get_x() + p.get_width() / 2., p.get_height()), 
       ha = 'center', va = 'center', xytext = (0, 10), textcoords = 'offset points')

解决方案 7:

我希望这对第 2 项有帮助:

a) 您可以按账单总额排序,然后将索引重置为此列

b) 使用调色板 =“Blue”使用此颜色将图表从浅蓝色缩放为深蓝色(如果从深蓝色缩放为浅蓝色,则使用调色板 =“Blues_d”)

import pandas as pd
import seaborn as sns
%matplotlib inline

df = pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')
groupedvalues = df.groupby('day').sum().reset_index()
groupedvalues = groupedvalues.sort_values('total_bill').reset_index()
g = sns.barplot(x='day', y='tip', data=groupedvalues, palette="Blues")

解决方案 8:

一个简单的方法是添加下面的代码(对于 Seaborn):

for p in splot.patches:
    splot.annotate(format(p.get_height(), '.1f'),
                   (p.get_x() + p.get_width() / 2., p.get_height()),
                   ha = 'center', va = 'center',
                   xytext = (0, 9),
                   textcoords = 'offset points')

例子:

splot = sns.barplot(df['X'], df['Y'])
# Annotate the bars in plot
for p in splot.patches:
    splot.annotate(format(p.get_height(), '.1f'),
                   (p.get_x() + p.get_width() / 2., p.get_height()),
                   ha = 'center', va = 'center',
                   xytext = (0, 9),
                   textcoords = 'offset points')
plt.show()
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1267  
  IPD(Integrated Product Development)即集成产品开发,是一套先进的、成熟的产品开发管理理念、模式和方法。随着市场竞争的日益激烈,企业对于提升产品开发效率、降低成本、提高产品质量的需求愈发迫切,IPD 项目管理咨询市场也迎来了广阔的发展空间。深入探讨 IPD 项目管理咨询的市场需求与发展,...
IPD集成产品开发流程   27  
  IPD(Integrated Product Development)产品开发流程是一套先进的、被广泛应用的产品开发管理体系,它涵盖了从产品概念产生到产品推向市场并持续优化的全过程。通过将市场、研发、生产、销售等多个环节紧密整合,IPD旨在提高产品开发的效率、质量,降低成本,增强企业的市场竞争力。深入了解IPD产品开发...
IPD流程中TR   31  
  IPD(Integrated Product Development)测试流程是确保产品质量、提升研发效率的关键环节。它贯穿于产品从概念到上市的整个生命周期,对企业的成功至关重要。深入理解IPD测试流程的核心要点,有助于企业优化研发过程,打造更具竞争力的产品。以下将详细阐述IPD测试流程的三大核心要点。测试策略规划测试...
华为IPD   26  
  华为作为全球知名的科技企业,其成功背后的管理体系备受关注。IPD(集成产品开发)流程作为华为核心的产品开发管理模式,在创新管理与技术突破方面发挥了至关重要的作用。深入剖析华为 IPD 流程中的创新管理与技术突破,对于众多企业探索自身发展路径具有重要的借鉴意义。IPD 流程概述IPD 流程是一种先进的产品开发管理理念和方...
TR评审   26  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用