Seaborn 条形图 - 显示值

Seaborn Barplot - Displaying Values

我正在寻找如何在 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/master/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")

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

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()

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/master/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 超出轴 0 的范围,大小为 4

希望这对项目 #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")

让我们坚持使用链接问题 () 中的解决方案。您想要使用 argsort 来确定用于为条形着色的颜色顺序。在链接的问题中,argsort 应用于 Series 对象,它工作正常,而这里你有一个 DataFrame。所以你需要 select 该 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 开始而不是零。所以必须从数组中减去 1。同样对于索引,我们需要整数值,因此我们需要将其转换为 int.

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

适用于单轴或轴矩阵(子图)

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)

为了以防万一有人对标记 水平条形图 感兴趣,我修改了 如下:

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 - 值文本和栏的上边缘之间的 space。仅适用于水平模式。

示例:

show_values_on_bars(sns_t, "h", 0.3)

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

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

matplotlib 3.4.0 的新功能

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

  • 对于单组条形图,传递单条形容器:

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

  • 对于多组条形图(带hue),迭代多个条形容器:

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

更多详情:

  • How to label count plotssns.countplotsns.catplot
  • fmt 参数)
  • labels 参数)
  • How to label thresholded bar plots

彩排版

Is there a way to scale the colors of the bars, with the lowest value of total_bill having the lightest color (in this case Friday) and the highest value of total_bill having the darkest?

  1. 找到每个 total_bill 值的排名:

    • 或者使用Series.sort_values:

      ranks = groupedvalues.total_bill.sort_values().index
      # Int64Index([1, 0, 3, 2], dtype='int64')
      
    • 或压缩欧内斯特的Series.rank version by chaining Series.sub:

      ranks = groupedvalues.total_bill.rank().sub(1).astype(int).array
      # [1, 0, 3, 2]
      
  2. 然后使用 ranks:

    重新索引调色板
    palette = sns.color_palette('Blues_d', len(ranks))
    ax = sns.barplot(x='day', y='tip', palette=np.array(palette)[ranks], data=groupedvalues)