Seaborn技术问题:为双变量kdeplot添加边缘直方图
jointplot) Got it, since you can't use jointplot but want those handy edge histograms alongside your two bivariate KDE plots, here's a flexible, manual approach using matplotlib's gridspec to build the layout from scratch. This gives you full control over every component, no restrictions from jointplot.
Step-by-Step Implementation
First, we'll set up a grid layout where the main plot takes up most of the space, with small subplots above and to the right for the edge histograms.
import matplotlib.pyplot as plt import seaborn as sns import matplotlib.gridspec as gridspec # Define the grid layout: 2 rows, 2 columns # Width/height ratios prioritize the main plot, tight spacing removes gaps gs = gridspec.GridSpec( 2, 2, width_ratios=[4, 1], # Main plot is 4x wider than right edge plot height_ratios=[1, 4], # Main plot is 4x taller than top edge plot wspace=0.05, # Minimal horizontal gap between subplots hspace=0.05 # Minimal vertical gap between subplots ) fig = plt.figure(figsize=(8, 8)) # Create each subplot ax_main = fig.add_subplot(gs[1, 0]) # Main plot (bottom-left) ax_top = fig.add_subplot(gs[0, 0], sharex=ax_main) # Top edge plot (shares x-axis with main) ax_right = fig.add_subplot(gs[1, 1], sharey=ax_main) # Right edge plot (shares y-axis with main)
Next, add your existing KDE plots to the main axis—this is exactly what you already had, just targeting the main subplot:
# Plot your dual bivariate KDEs on the main axis sns.kdeplot(df_c['attr1'], df_c['attr2'], ax=ax_main, cmap='Blues', shade_lowest=False) sns.kdeplot(df_n['attr1'], df_n['attr2'], ax=ax_main, cmap='Reds', shade_lowest=False)
Now add the edge histograms. We'll use histplot for the bars, and optionally overlay KDE curves for smoother distribution visualization:
# Top edge: Histograms for attr1 (from both DataFrames) sns.histplot(df_c['attr1'], ax=ax_top, color='blue', alpha=0.5, kde=False, bins=20) sns.histplot(df_n['attr1'], ax=ax_top, color='red', alpha=0.5, kde=False, bins=20) # Clean up the top plot: Hide y-axis labels/ticks (they're irrelevant here) ax_top.set_ylabel('') ax_top.tick_params(axis='y', labelleft=False) # Right edge: Horizontal histograms for attr2 (from both DataFrames) sns.histplot(df_c['attr2'], ax=ax_right, color='blue', alpha=0.5, kde=False, bins=20, orient='h') sns.histplot(df_n['attr2'], ax=ax_right, color='red', alpha=0.5, kde=False, bins=20, orient='h') # Clean up the right plot: Hide x-axis labels/ticks ax_right.set_xlabel('') ax_right.tick_params(axis='x', labelbottom=False)
Optional Enhancements
If you want to add smooth KDE curves on top of the histograms (like jointplot sometimes does), just add these lines:
# Add KDE curves to the top edge plot sns.kdeplot(df_c['attr1'], ax=ax_top, color='darkblue', linewidth=1.5) sns.kdeplot(df_n['attr1'], ax=ax_top, color='darkred', linewidth=1.5) # Add vertical KDE curves to the right edge plot sns.kdeplot(df_c['attr2'], ax=ax_right, color='darkblue', linewidth=1.5, vertical=True) sns.kdeplot(df_n['attr2'], ax=ax_right, color='darkred', linewidth=1.5, vertical=True)
Why This Works
- The
gridspecsetup lets you precisely control the size and spacing of each subplot, avoiding the rigid structure ofjointplot. - Using
sharex/shareyensures the edge plots align perfectly with the main KDE plot's axes. - You can customize every detail: histogram bin counts, colors, transparency, whether to include KDE curves, and more.
内容的提问来源于stack exchange,提问作者malexmave

