在小提琴图上绘制蜂群图会改变 ylim 并截断小提琴。

3
import seaborn as sns
import numpy as np  # for sample data
import pandas as pd

# sample data
np.random.seed(365)
rows = 60
data1 = {'Type 1': ['a'] * rows,
         'Total': np.random.normal(loc=25, scale=3, size=rows)}
data2 = {'Type 1': ['b'] * rows,
         'Total': np.random.normal(loc=60, scale=7, size=rows)}
df = pd.concat([pd.DataFrame(d) for d in [data1, data2]], ignore_index=True)

# plot
plt.figure(figsize=(5, 4))
sns.violinplot(x='Type 1', y= 'Total', data=df, inner=None)
sns.swarmplot(x='Type 1', y= 'Total', data=df, color='#000000', size=3)

enter image description here

与没有使用swarmplot的图表相比较

enter image description here

显示如上图像,我该如何更改显示的范围?

我尝试过更改figsize在我将swarmplot重叠到violetplot之前,我没有遇到这个问题。

df

  Type 1      Total
0      a  25.503763
1      a  26.570516
2      a  27.452127
3      a  30.111537
4      a  18.559157
...
115      b  67.389032
116      b  67.337122
117      b  59.193256
118      b  56.356515
119      b  57.353019

当有人回答我的问题时我该怎么办? - Trenton McKinney
希望答案有所帮助。详细回答问题需要耗费时间。如果您的问题已经得到解决,请接受解决方案。✔符号位于答案左上角的▲/▼箭头下方。如果有更好的解决方案出现,可以接受新的解决方案。如果您拥有15+的声望值,也可以使用▲/▼箭头投票以评估答案的实用性。如果解决方案无法回答您的问题,请留下评论。当有人回答我的问题时我该怎么做? - Trenton McKinney
1个回答

2
当将`sns.swarmplot`或`sns.stripplot`添加到`sns.violinplot`时,y轴的限制会发生变化。
这种情况在使用显式的“Axes”接口隐式的“pyplot”接口时都会发生,如此图表所示。
使用`sns.catplot`和`kind='violin'`,以及使用`map_dataframe`和`sns.swarmplot`也会产生相同的问题,如此图表所示。
如果在`sns.boxplot`上绘制`sns.swarmplot`,则不会发生这种情况,如此图表所示。 在`python 3.11.2`、`matplotlib 3.7.1`和`seaborn 0.12.2`中进行了测试
import seaborn as sns
import matplotlib.pyplot as plt

# sample data
df = sns.load_dataset('geyser')

# plot
sns.violinplot(data=df, x='kind', y='duration', inner=None)
print('ylim with 1 plot', plt.ylim())
sns.swarmplot(data=df, x='kind', y='duration', color='#000000', size=3)
print('ylim with both plots', plt.ylim())

ylim with 1 plot (1.079871611291212, 5.607761736565478)
ylim with both plots (1.425, 5.2749999999999995)

enter image description here

解决方案

  • 以下是解决问题的三个选项:
    1. 在绘制完sns.violinplot后,捕获ylim值,并在绘制sns.swarmplot后将ylim设置为这些值。
    2. 在绘制sns.swarmplot后,将ylim设置为特定值。
    3. 先绘制sns.swarmplot,然后再绘制sns.violinplot
  • 要使ylim从"原点"开始,使用y_bot = 0
  • 使用{{link1:matplotlib.pyplot.ylim}}、{{link2:matplotlib.axes.Axes.set_ylim}}和{{link3:matplotlib.axes.Axes.get_ylim}}。

1.

sns.violinplot(data=df, x='kind', y='duration', inner=None)
y_bot, y_top = plt.ylim()
sns.swarmplot(data=df, x='kind', y='duration', color='#000000', size=3)
plt.ylim(y_bot, y_top)

enter image description here

2.
sns.violinplot(data=df, x='kind', y='duration', inner=None)
sns.swarmplot(data=df, x='kind', y='duration', color='#000000', size=3)
plt.ylim(1, 6)

enter image description here

3.
# plot
sns.swarmplot(data=df, x='kind', y='duration', color='#000000', size=3)
print('ylim with 1 plot', plt.ylim())
sns.violinplot(data=df, x='kind', y='duration', inner=None)
print('ylim with both plots', plt.ylim())

ylim with 1 plot (1.425, 5.2749999999999995)
ylim with both plots (1.079871611291212, 5.607761736565478)

enter image description here

优先使用显式接口

plt.figure.add_subplot

fig = plt.figure(figsize=(8, 5))
ax = fig.add_subplot()
sns.violinplot(data=df, x='kind', y='duration', inner=None, ax=ax)
y_bot, y_top = ax.get_ylim()
sns.swarmplot(data=df, x='kind', y='duration', color='#000000', size=3, ax=ax)
ax.set_ylim(y_bot, y_top)

plt.subplots

fig, axes = plt.subplots(figsize=(8, 5))
sns.violinplot(data=df, x='kind', y='duration', inner=None, ax=ax)
y_bot, y_top = ax.get_ylim()
sns.swarmplot(data=df, x='kind', y='duration', color='#000000', size=3, ax=ax)
ax.set_ylim(y_bot, y_top)

```python df[['duration', 'kind']].head() ```
  • 这个真实数据与原始帖子中的随机样本类似。
   duration   kind
0     3.600   long
1     1.800  short
2     3.333   long
3     2.283  short
4     4.533   long

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接