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

cetgtptt  于 2023-04-21  发布在  其他
关注(0)|答案(8)|浏览(151)

我想看看如何在Seaborn中使用条形图来显示数据框中的值,而不是图形中的值。
1.我希望在数据框中显示一个字段的值,同时绘制另一个字段的图形。例如,下面,我正在绘制“tip”,但我想将'total_bill'的值居中放置在每个条形图的上方(i.e.325.88在周五上方,1778.40在周六上方,等等)。
1.有没有一种方法可以缩放条形图的颜色,使'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")

但这给了我以下错误:
属性错误:“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的界限

ccgok5k5

ccgok5k51#

matplotlib 3.4.0新增

现在有一个内置的Axes.bar_label来自动标记bar容器:

  • 对于单组条形图,传递单条形容器:
ax = sns.barplot(x='day', y='tip', data=groupedvalues)
ax.bar_label(ax.containers[0], fmt='%.1f')

  • 对于多组条形图(带hue),迭代多个条形容器:
ax = sns.barplot(x='day', y='tip', hue='sex', data=df)
for container in ax.containers:
    ax.bar_label(container, fmt='%.1f')

更多详情:

颜色分级版本

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

ranks = groupedvalues.total_bill.sort_values().index
# Int64Index([1, 0, 3, 2], dtype='int64')
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)

vc6uscn9

vc6uscn92#

这适用于单个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)
a0zr77ik

a0zr77ik3#

坚持使用Changing color scale in seaborn bar plot的解决方案,它使用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日的answer,以了解.bar_label的详细解释,并提供文档和示例链接。
  • day列以category Dtype的形式下载,这样可以按顺序显示一周中的日期。这也可以确保x轴上的条形图和tb中的值的绘图顺序。
  • .bar_label从左到右添加标签,因此tb中的值与条形图的顺序相同。
  • 如果使用非分类列,则可以在列上使用pd.Categorical来设置顺序。
  • sns.barplot中,指定estimator=sumtip求和。默认值为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()

5f0d552i

5f0d552i4#

为了防止有人对水平条形图的标注感兴趣,我修改了Sharon's answer如下:

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)

pwuypxnk

pwuypxnk5#

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')
sq1bmfud

sq1bmfud6#

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')
7gyucuyw

7gyucuyw7#

希望对#2有帮助:
a)您可以按总账单排序,然后将索引重置到此列
B)使用palette=“Blue”使用此颜色将图表从浅蓝色缩放到深蓝色(如果深蓝色到浅蓝色,则使用palette=“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")
cl25kdpy

cl25kdpy8#

一个简单的方法是添加下面的代码(对于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()

相关问题