【问题标题】:Seaborn workaround for hue barplot色调条形图的 Seaborn 解决方法
【发布时间】:2017-09-12 14:00:25
【问题描述】:

我在 Jupyter 笔记本 上有以下 DataFrame,它使用 seaborn 绘制条形图:

data = {'day_index': [0, 1, 2, 3, 4, 5, 6],
        'avg_duration': [708.852242, 676.7021900000001, 684.572677, 708.92534, 781.767476, 1626.575057, 1729.155673],
        'trips': [114586, 120936, 118882, 117868, 108036, 43740, 37508]}

df = pd.DataFrame(data)

daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

plt.figure(figsize=(16,10));
sns.set_style('ticks')
ax = sns.barplot(data=df, \
                 x='day_index', \
                 y='avg_duration', \
                 hue='trips', \
                 palette=sns.color_palette("Reds_d", n_colors=7, desat=1))

ax.set_xlabel("Week Days", fontsize=18, alpha=0.8)
ax.set_ylabel("Duration (seconds)", fontsize=18, alpha=0.8)
ax.set_title("Week's average Trip Duration", fontsize=24)
ax.set_xticklabels(daysOfWeek, fontsize=16)
ax.legend(fontsize=15)
sns.despine()
plt.show()

情节 A:

可以看出,条形与 x_ticklabels 不匹配并且非常细。
如果我删除 hue='trips' 部分,这一切都已修复,这是一个已知的 seaborn 问题。 虽然在可视化中显示行程数量非常重要,但是:有没有办法绕过 seaborn(可能直接使用 matplotlib)添加色调属性?

【问题讨论】:

    标签: python pandas matplotlib data-visualization seaborn


    【解决方案1】:

    hue 参数可能只对在绘图中引入新维度有意义,而不是在同一维度上显示另一个数量。

    最好在没有hue 参数的情况下绘制条形图(实际上将其称为色调很容易产生误导),并根据"trips" 列中的值简单地对条形图着色。

    这也显示在这个问题中:Seaborn Barplot - Displaying Values

    这里的代码如下所示:

    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np
    
    di = np.arange(0,7)
    avg  = np.array([708.852242,676.702190,684.572677,708.925340,781.767476,
                     1626.575057,1729.155673])
    trips = np.array([114586,120936,118882,117868,108036,43740,37508])
    df = pd.DataFrame(np.c_[di, avg, trips], columns=["day_index","avg_duration", "trips"])
    
    daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', \
    'Friday', 'Saturday', 'Sunday']
    
    plt.figure(figsize=(10,7));
    sns.set_style('ticks')
    v  = df.trips.values
    colors=plt.cm.viridis((v-v.min())/(v.max()-v.min()))
    ax = sns.barplot(data=df, x='day_index',   y='avg_duration', palette=colors)
    
    for index, row in df.iterrows():
        ax.text(row.day_index,row.avg_duration, row.trips, color='black', ha="center")
    
    ax.set_xlabel("Week Days", fontsize=16, alpha=0.8)
    ax.set_ylabel("Duration (seconds)", fontsize=16, alpha=0.8)
    ax.set_title("Week's average Trip Duration", fontsize=18)
    ax.set_xticklabels(daysOfWeek, fontsize=14)
    ax.legend(fontsize=15)
    sns.despine()
    plt.show()
    

    【讨论】:

      【解决方案2】:

      我认为在这种情况下您不需要指定hue 参数:

      In [136]: ax = sns.barplot(data=dfGroupedAgg, \
           ...:                  x='day_index', \
           ...:                  y='avg_duration', \
           ...:                  palette=sns.color_palette("Reds_d", n_colors=7, desat=1))
           ...:
      

      您可以添加行程数量作为注释:

      def autolabel(rects, labels=None, height_factor=1.05):
          for i, rect in enumerate(rects):
              height = rect.get_height()
              if labels is not None:
                  try:
                      label = labels[i]
                  except (TypeError, KeyError):
                      label = ' '
              else:
                  label = '%d' % int(height)
              ax.text(rect.get_x() + rect.get_width()/2., height_factor*height,
                      '{}'.format(label),
                      ha='center', va='bottom')
      
      autolabel(ax.patches, labels=df.trips, height_factor=1.02)
      

      【讨论】:

        【解决方案3】:

        解决办法

        ax = sns.barplot(data=df, \
                         x='day_index', \
                         y='avg_duration', \
                         hue='trips', \
                         dodge=False, \
                         palette=sns.color_palette("Reds_d", n_colors=7, desat=1))
        

        【讨论】:

          【解决方案4】:

          从彩色地图构建图例

          • 删除hue。如前所述,使用此参数时,条不会居中,因为它们是根据色调级别的数量放置的,在这种情况下有 7 个级别。
          • 使用palette 参数而不是hue,将条形图直接放置在刻度上方。
          • 此选项需要“手动”将'trips' 与颜色关联并创建图例。
            • patches 使用 Patch 创建图例中的每个项目。 (例如,与颜色和名称相关联的矩形)。
          import pandas as pd
          import matplotlib.pyplot as plt
          import seaborn as sns
          from matplotlib.patches import Patch
          
          daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
          
          # specify the colors
          colors = sns.color_palette('Reds_d', n_colors=len(df))
          
          # create the plot
          plt.figure(figsize=(16,10))
          p = sns.barplot(data=df, x='day_index', y='avg_duration', palette=colors)
          
          # plot cosmetics
          p.set_xlabel("Week Days", fontsize=18, alpha=0.8)
          p.set_ylabel("Average Duration (seconds)", fontsize=18, alpha=0.8)
          p.set_title("Week's average Trip Duration", fontsize=24)
          p.set_xticklabels(daysOfWeek, fontsize=16)
          sns.despine()
          
          # setup the legend
          
          # map names to colors
          cmap = dict(zip(df.trips, colors))
          
          # create the rectangles for the legend
          patches = [Patch(color=v, label=k) for k, v in cmap.items()]
          
          # add the legend
          plt.legend(title='Number of Trips', handles=patches, bbox_to_anchor=(1.04, 0.5), loc='center left', borderaxespad=0, fontsize=15)
          

          【讨论】:

            猜你喜欢
            • 2016-05-15
            • 2023-03-29
            • 2018-10-16
            • 1970-01-01
            • 2020-02-19
            • 2020-01-05
            • 2022-01-16
            • 2022-01-11
            相关资源
            最近更新 更多