Seaborn箱图单个箱间距

时间:2018-06-29 15:38:07

标签: python matplotlib seaborn boxplot

如何在seaborn箱图中增加两个特定箱之间的空间?在提示数据集中,如何在不影响其他框的情况下修改Sat和Sun之间的间距。我已经在数据框中添加了空列,但是采用这种解决方法无法控制间距。

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

Tips Boxplot Example

2 个答案:

答案 0 :(得分:1)

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

最简单的解决方法是使用其他boxplot函数,例如pandas数据框随附的函数:

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

当然,这与Seaborn版本的样式相差甚远。

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

这很接近:

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

enter image description here

答案 1 :(得分:0)

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

可能需要根据您的实际情况进行调整。