如何在violinplot后插入regplot?组合绘图位置偏移问题求助
解决regplot与violinplot组合绘制时的位置偏移问题
问题原因
同时使用sns.regplot()和sns.violinplot()时,两者对x轴变量的处理逻辑存在差异:
regplot将Magnitudes视为数值变量,会根据数值实际大小在x轴上定位violinplot将Magnitudes视为分类变量,会把每个类别均匀分布在x轴上
这种处理方式的不同直接导致两个图层位置偏移。
修复方案
方法1:让regplot匹配分类变量的位置
先绘制violinplot获取分类位置,再将regplot的x值映射为对应分类索引,确保两者位置对齐:
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt # 替换为你的真实数据 magnitudes = np.random.choice([1,2,3,4], size=100) lengths = np.random.exponential(scale=10, size=100) widths = np.random.exponential(scale=8, size=100) df = pd.DataFrame({'Magnitudes': magnitudes, 'Lengths': np.log10(lengths), 'Widths': np.log10(widths)}) palette = sns.color_palette("Set2", len(df['Magnitudes'].unique())) sns.set_style("darkgrid", {"grid.color": ".6", "grid.linestyle": ":"}) plt.figure(figsize=(10,8)) # 第一个子图:Lengths vs Magnitude plt.subplot(2, 1, 1) # 先绘制violinplot并获取轴对象 violin_ax = sns.violinplot(x='Magnitudes', y='Lengths', data=df, palette=palette, alpha=0.5, hue='Magnitudes', legend=False) # 获取x轴分类的坐标位置 x_positions = np.array([tick.get_loc() for tick in violin_ax.get_xticks()]) # 将Magnitudes转换为分类索引 df['x_category'] = pd.Categorical(df['Magnitudes']).codes # 绘制regplot,使用分类索引作为x sns.regplot(x='x_category', y='Lengths', data=df, scatter_kws={"alpha": 0.0}, ax=violin_ax) # 重置x轴标签为原始Magnitudes值 plt.xticks(x_positions, df['Magnitudes'].unique()) plt.title('Violin Plot of Lengths vs Magnitude') plt.xlabel('Magnitude') plt.ylabel('Lengths') # 第二个子图:Widths vs Magnitude plt.subplot(2, 1, 2) violin_ax2 = sns.violinplot(x='Magnitudes', y='Widths', data=df, palette=palette, alpha=0.5, hue='Magnitudes', legend=False) x_positions2 = np.array([tick.get_loc() for tick in violin_ax2.get_xticks()]) df['x_category2'] = pd.Categorical(df['Magnitudes']).codes sns.regplot(x='x_category2', y='Widths', data=df, scatter_kws={"alpha": 0.0}, ax=violin_ax2) plt.xticks(x_positions2, df['Magnitudes'].unique()) plt.title('Violin Plot of Widths vs Magnitude') plt.xlabel('Magnitude') plt.ylabel('Widths') plt.tight_layout() plt.show()
方法2:用catplot统一基础图层
使用sns.catplot()绘制小提琴图,再为每个子图添加回归线,逻辑更简洁:
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt # 替换为你的真实数据 magnitudes = np.random.choice([1,2,3,4], size=100) lengths = np.random.exponential(scale=10, size=100) widths = np.random.exponential(scale=8, size=100) df = pd.DataFrame({'Magnitudes': magnitudes, 'Lengths': np.log10(lengths), 'Widths': np.log10(widths)}) palette = sns.color_palette("Set2", len(df['Magnitudes'].unique())) sns.set_style("darkgrid", {"grid.color": ".6", "grid.linestyle": ":"}) # 绘制Lengths的图 g = sns.catplot(data=df, x='Magnitudes', y='Lengths', kind='violin', palette=palette, alpha=0.5, hue='Magnitudes', legend=False) for ax in g.axes.flat: # 将Magnitudes转为分类索引 x_cat = pd.Categorical(df['Magnitudes']).codes sns.regplot(x=x_cat, y=df['Lengths'], data=df, scatter_kws={"alpha":0.0}, ax=ax) ax.set_xticks(ax.get_xticks()) ax.set_xticklabels(df['Magnitudes'].unique()) g.fig.suptitle('Violin Plot of Lengths vs Magnitude', y=1.02) # 绘制Widths的图 g2 = sns.catplot(data=df, x='Magnitudes', y='Widths', kind='violin', palette=palette, alpha=0.5, hue='Magnitudes', legend=False) for ax in g2.axes.flat: x_cat = pd.Categorical(df['Magnitudes']).codes sns.regplot(x=x_cat, y=df['Widths'], data=df, scatter_kws={"alpha":0.0}, ax=ax) ax.set_xticks(ax.get_xticks()) ax.set_xticklabels(df['Magnitudes'].unique()) g2.fig.suptitle('Violin Plot of Widths vs Magnitude', y=1.02) plt.show()
效果说明
两种方法都能让回归线精准对齐每个小提琴图的中心,彻底解决位置偏移问题。
内容的提问来源于stack exchange,提问作者Alex Villarroel Carrasco
相关产品推荐
相关产品推荐

