并排绘制两个图形时,seaborn kdeplot() 出现问题

问题描述 投票:0回答:1

我正在尝试在图的顶部和侧面绘制两个二维分布及其边际分布,如下所示: enter image description here

现在我想将上图与下图组合起来,使它们并排出现: enter image description here

但是,这样做时,并未绘制边际分布。任何人都可以帮忙吗? enter image description here

绘制上图的代码在这里给出:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import multivariate_normal
import ot
import ot.plot

# Define the mean and covariance for two different multivariate normal distributions
mean1 = [0, 0]
cov1 = [[1, 0.5], [0.5, 1]]

mean2 = [3, 3]
cov2 = [[1, -0.5], [-0.5, 1]]

n = 100

# Generate random samples from the distributions
np.random.seed(0)
samples1 = np.random.multivariate_normal(mean1, cov1, size=n)
samples2 = np.random.multivariate_normal(mean2, cov2, size=n)

df1 = pd.DataFrame(np.concatenate([samples1, samples2]), columns=['X', 'Y'])
df1['Distribution'] = 'Target'
df1['Distribution'].iloc[n:] = 'Source'

# Create a custom palette with blue and red
custom_palette = {'Target': 'blue', 'Source': 'red'}

# Plotting side by side
fig, axs = plt.subplots(1, 2, figsize=(12, 4))

# Jointplot using seaborn
g = sns.kdeplot(data=df1, x="X", y="Y", hue="Distribution", kind="kde", space=0, fill=True, palette=custom_palette, ax=axs[0])
axs[0].set_xlim(-4, 6.5)
axs[0].set_ylim(-4, 6.5)
# axs[0].set_aspect('equal', adjustable='box')
sns.move_legend(axs[0], "lower right")

# Optimal Transport matching between the samples
a, b = np.ones((n,)) / n, np.ones((n,)) / n  # uniform distribution on samples
M = ot.dist(samples2, samples1, metric='euclidean')
G0 = ot.emd(a, b, M)
ot.plot.plot2D_samples_mat(samples2, samples1, G0, c=[.5, .5, 1])
axs[1].plot(samples2[:, 0], samples2[:, 1], '+r', markersize=10, label='Source samples')  # Increased marker size
axs[1].plot(samples1[:, 0], samples1[:, 1], 'xb', markersize=10, label='Target samples')  # Increased marker size
axs[1].legend(loc=4)

# Common labels and limits
for ax in axs:
    ax.set(xlabel='X')
    ax.set_xlim([-4, 6.5])
    ax.set_ylim([-4, 6.5])

# Remove y-axis from the second figure
axs[1].set(ylabel='')
axs[1].yaxis.set_visible(False)

# Adjust layout and save plot as PDF
fig.tight_layout()

# Show plot
plt.show()
python seaborn kdeplot
1个回答
0
投票

您不能直接执行此操作,因为边际分布需要

jointplot
,这是图形级图,不能直接添加额外的轴。

然而,修改

JointGrid
代码以添加更多轴是相当容易的。

关键是改变:

# add more space to accommodate an extra plot
# gs = plt.GridSpec(ratio + 1, ratio + 1)
gs = plt.GridSpec(ratio + 1, ratio + 1 + ratio)

# change how the space is defined (example for the ax_joint)
# ax_joint = f.add_subplot(gs[1:, :-1])   # use all width but last
ax_joint = f.add_subplot(gs[1:, :ratio])  # use first "ratio" slots

这给了我们:

ratio = 5
space = .2

f = plt.figure(figsize=(12, 4))
gs = plt.GridSpec(ratio + 1, ratio + 1 + ratio)
ax_joint = f.add_subplot(gs[1:, :ratio])
ax_marg_x = f.add_subplot(gs[0, :ratio], sharex=ax_joint)
ax_marg_y = f.add_subplot(gs[1:, ratio], sharey=ax_joint)
ax_ot = f.add_subplot(gs[1:, ratio+1:], sharey=ax_joint)

# Turn off tick visibility for the measure axis on the marginal plots
plt.setp(ax_marg_x.get_xticklabels(), visible=False)
plt.setp(ax_marg_y.get_yticklabels(), visible=False)
plt.setp(ax_marg_x.get_xticklabels(minor=True), visible=False)
plt.setp(ax_marg_y.get_yticklabels(minor=True), visible=False)
plt.setp(ax_marg_x.yaxis.get_majorticklines(), visible=False)
plt.setp(ax_marg_x.yaxis.get_minorticklines(), visible=False)
plt.setp(ax_marg_y.xaxis.get_majorticklines(), visible=False)
plt.setp(ax_marg_y.xaxis.get_minorticklines(), visible=False)
plt.setp(ax_marg_x.get_yticklabels(), visible=False)
plt.setp(ax_marg_y.get_xticklabels(), visible=False)
plt.setp(ax_marg_x.get_yticklabels(minor=True), visible=False)
plt.setp(ax_marg_y.get_xticklabels(minor=True), visible=False)
ax_marg_x.yaxis.grid(False)
ax_marg_y.xaxis.grid(False)

utils = sns.axisgrid.utils
utils.despine(ax=ax_marg_x, left=True)
utils.despine(ax=ax_marg_y, bottom=True)
for axes in [ax_marg_x, ax_marg_y]:
    for axis in [axes.xaxis, axes.yaxis]:
        axis.label.set_visible(False)
f.tight_layout()
f.subplots_adjust(hspace=space, wspace=space)

sns.kdeplot(data=df1, x='X', y='Y', hue='Distribution', fill=True, palette=custom_palette, ax=ax_joint)
sns.move_legend(ax_joint, 'lower right')
sns.kdeplot(data=df1, x='X', hue='Distribution', fill=True, palette=custom_palette, legend=False,
            ax=ax_marg_x)
sns.kdeplot(data=df1, y='Y', hue='Distribution', fill=True, palette=custom_palette, legend=False,
            ax=ax_marg_y)

# Optimal Transport matching between the samples
a, b = np.ones((n,)) / n, np.ones((n,)) / n  # uniform distribution on samples
M = ot.dist(samples2, samples1, metric='euclidean')
G0 = ot.emd(a, b, M)
ot.plot.plot2D_samples_mat(samples2, samples1, G0, c=[.5, .5, 1])
ax_ot.plot(samples2[:, 0], samples2[:, 1], '+r', markersize=10, label='Source samples')  # Increased marker size
ax_ot.plot(samples1[:, 0], samples1[:, 1], 'xb', markersize=10, label='Target samples')  # Increased marker size
ax_ot.legend(loc=4)

输出:

seaborn jointplot with extra ax

© www.soinside.com 2019 - 2024. All rights reserved.