【问题标题】:Seaborn boxplot individual box spacingSeaborn boxplot 单个框间距
【发布时间】:2018-12-08 20:31:00
【问题描述】:

如何增加 seaborn boxplot 中两个特定框之间的空间?在提示数据集中,我如何修改 Sat 和 Sun 之间的间距而不影响其他框。我已经在数据框中包含了空列,但是使用此解决方法无法控制间距。

%matplotlib inline
import seaborn as sns
tips = sns.load_dataset("tips")
ax = sns.boxplot(x="day", y="total_bill", data=tips)

【问题讨论】:

    标签: python matplotlib seaborn boxplot


    【解决方案1】:

    据我所知,seaborn 无法做到这一点,因为遗憾的是它没有提供任何修改 positions 关键字的方法。另见this similar question

    最简单的解决方法是使用不同的箱线图功能,例如 pandas 数据框附带的功能:

    bplot = tips.boxplot(by="day", column="total_bill", positions=[1,2,3,4.5])
    

    当然,这远没有 seaborn 版本那么漂亮。

    幸运的是,matplotlib 为那些愿意探索它们的人提供了无限的选择,因此人们可以通过相应地修改情节的不同部分来创建类似于 seaborn 情节的东西。

    这就接近了:

    # Prep
    import matplotlib.pyplot as plt
    import seaborn as sns
    tips = sns.load_dataset("tips")
    
    # Create boxplot
    bplot = tips.boxplot(by="day", column="total_bill", positions=[1,2,3,4.5], 
                         return_type='dict', figsize=(8,6), grid=False, patch_artist=True, 
                         sym='d', fontsize=16)
    
    # Style boxplot
    colors = ['blue', 'green', 'red', 'cyan']
    for patch, color in zip(bplot['total_bill']['boxes'], colors):
        patch.set_facecolor(color)
        patch.set_edgecolor('0.2')
        patch.set_linewidth(1.5)
    for whisker in bplot['total_bill']['whiskers']:
        whisker.set_color('0.2')
        whisker.set_linewidth(1.5)
    for fliers in bplot['total_bill']['fliers']:
        fliers.set_markerfacecolor('0.2')
    for median in bplot['total_bill']['medians']:
        median.set_color('0.2')
        median.set_linewidth(1.5)
    for caps in bplot['total_bill']['caps']:
        caps.set_color('0.2')
        caps.set_linewidth(1.5)
    
    # Other adjustments
    plt.title("")
    plt.suptitle("")
    plt.xlabel("day", fontsize=18)
    plt.ylabel("total_bill", fontsize=18)
    

    【讨论】:

      【解决方案2】:

      Seaborn 不提供此功能(参见例如this issue)。您仍然可以在绘制方框后调整 matplotlib:

      ax = plt.gca()  # Or get the axis another way
      
      def _reduce_box_width(artist, factor=.5):
          vertices = artist.get_path().vertices
          artist_width = vertices[1, 0] - vertices[0, 0]
          vertices[0, 0] += artist_width * (factor/2)
          vertices[1, 0] -= artist_width * (factor/2)
          vertices[2, 0] -= artist_width * (factor/2)
          vertices[3, 0] += artist_width * (factor/2)
          vertices[4, 0] += artist_width * (factor/2)
      
      for artist in ax.artists:
          _reduce_box_width(artist, factor=.5)
      
      def _reduce_horizontal_line_width(artist, factor=.5):
          vertices = artist.get_path().vertices
          artist_width = vertices[1, 0] - vertices[0, 0]
          vertices[0, 0] += artist_width * (factor/2)
          vertices[1, 0] -= artist_width * (factor/2)
      
      horizontal_lines = [l for l in ax.lines
                          if len(l.get_path().vertices) != 0 and
                             l.get_path().vertices[0, 1] = = l.get_path().vertices[1, 1]]
      for line in horizontal_lines:
          _reduce_horizontal_line_width(line)
      
      ax.redraw_in_frame()
      

      可能需要根据您的具体情况进行调整。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-15
        • 1970-01-01
        • 2020-03-09
        • 2021-10-29
        • 1970-01-01
        • 1970-01-01
        • 2017-08-06
        • 1970-01-01
        相关资源
        最近更新 更多