如何用Seaborn在同一图表中绘制两个DataFrame的可视化图
Seaborn双DataFrame绘图问题解决方案
问题A:同一画布绘制两个数据集(同X/Y轴,不同hue)
问题原因
sb.relplot是Seaborn的FacetGrid高级接口,每次调用都会自动创建新的Figure对象,因此两次调用会生成独立图表,而非在同一张图上叠加。
解决方案
改用底层的sb.scatterplot(支持传入已有的matplotlib轴对象),在同一个轴上绘制两个数据集,手动控制hue样式:
import seaborn as sb import matplotlib.pyplot as plt import pandas as pd import numpy as np # 生成测试数据 df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD')) df['Name'] = 'Adam' df.iloc[::5, 4] = 'Berta' df1 = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD')) df1['Location'] = 'New York' df1.iloc[::5, 4] = 'Tokyo' # 创建画布和轴对象 fig, ax = plt.subplots(figsize=(11.7, 8.27)) # 在同一轴上绘制两个数据集 sb.scatterplot(data=df, x='Name', y='C', hue='Name', ax=ax) sb.scatterplot(data=df1, x='Location', y='C', hue='Location', ax=ax) # 调整图例位置,避免遮挡 ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.tight_layout() plt.show()
问题B:同Y轴、不同字符串X轴,右侧放置第二个散点图
问题原因
twinx()仅创建共享X轴的右侧Y轴,并未生成独立的X轴,因此第二个散点图会覆盖原X轴的显示。要实现右侧独立X轴,需使用twiny()并手动调整轴的位置和样式。
解决方案
通过twiny()创建共享Y轴的独立X轴,再调整轴的位置到右侧:
import seaborn as sb import matplotlib.pyplot as plt import pandas as pd import numpy as np # 生成测试数据 df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD')) df['Name'] = 'Adam' df.iloc[::5, 4] = 'Berta' df1 = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD')) df1['Location'] = 'New York' df1.iloc[::5, 4] = 'Tokyo' fig, ax = plt.subplots(figsize=(10, 6)) # 绘制左侧X轴的散点图 sb.scatterplot(data=df, x='Name', y='A', hue='Name', ax=ax) ax.set_ylabel('Amount') ax.set_xlabel('Name') # 创建右侧独立X轴 ax2 = ax.twiny() sb.scatterplot(data=df1, x='Location', y='A', hue='Location', ax=ax2) # 调整右侧X轴位置到右侧,设置标签方向 ax2.spines['right'].set_position(('outward', 60)) ax2.spines['right'].set_visible(True) ax2.spines['top'].set_visible(False) ax2.xaxis.set_label_position('right') ax2.xaxis.tick_right() ax2.set_xlabel('Location') ax2.set_xticklabels(ax2.get_xticklabels(), rotation=90) # 合并图例,移除重复项 handles1, labels1 = ax.get_legend_handles_labels() handles2, labels2 = ax2.get_legend_handles_labels() ax.legend(handles1 + handles2, labels1 + labels2, bbox_to_anchor=(1.3, 1)) ax2.get_legend().remove() plt.tight_layout() plt.show()
说明
twiny()创建的轴默认显示在顶部,通过调整spines参数可以将其移到右侧- 字符串类型X轴的标签需要旋转,避免重叠
- 手动合并图例可以避免出现两个独立图例,提升可读性
内容的提问来源于stack exchange,提问作者MisterY
相关产品推荐
相关产品推荐

