如何在条形图上显示自定义值
- 2025-02-13 08:36:00
- admin 原创
- 26
问题描述:
我想了解如何在 Seaborn 中做两件事:使用条形图显示数据框中存在但不在图表中的值。
我希望在绘制数据框中一个字段的值的同时显示另一个字段的值。例如,下面,我正在绘制“tip”,但我想将值置于
'total_bill'
每个条形图上方的中心位置(即星期五上方为 325.88,星期六上方为 1778.40,等等)。有没有办法缩放条形图的颜色,使最低值具有
'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`
对于自定义标签(例如,
tip
带有值的条形图total_bill
),请使用以下labels
参数:
ax = sns.barplot(x='day', y='tip', data=groupedvalues)
ax.bar_label(ax.containers[0], labels=groupedvalues['total_bill'])
# ----------------------------------
对于多组条形图(即带有
hue
),将会有多个需要迭代的条形容器:
ax = sns.barplot(x='day', y='tip', hue='sex', data=df)
for container in ax.containers:
ax.bar_label(container)
更多详细信息:
如何标记百分比计数(
fmt
参数)如何旋转标签(
rotation
参数)如何垂直居中标签(
label_type
参数)如何给标签添加间距(
padding
参数)
颜色排序版本
有没有办法缩放条形图的颜色,使最低值具有
total_bill
最浅的颜色(在本例中为星期五),最高值具有total_bill
最深的颜色?
找出每个值的等级
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]
然后使用以下命令重新索引调色板
ranks
:
palette = sns.color_palette('Blues_d', len(ranks))
ax = sns.barplot(x='day', y='tip', palette=np.array(palette)[ranks], data=groupedvalues)
解决方案 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
,以获得包含文档和示例链接的详细解释。
该
day
列将下载为category Dtype
,这样可以保持一周中各天的顺序。这还可以确保 x 轴上的条形图和 中的值的绘制顺序tb
。.bar_label
从左到右添加标签,因此中的值的tb
顺序与条形图的顺序相同。如果使用非分类列,
pd.Categorical
则可以在该列上使用它来设置顺序。
在 中
sns.barplot
,estimator=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()
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)