将 X 的色相图转换为色相图与模式(X 给定色相)?

convert hued displot of X to plot of hue vs mode(X given hue)?

我有一个带有色调变量的 Seaborn displot:

对于每个色调变量,我想提取密度估计的模式,然后绘制每个色调变量与其模式的关系图,如下所示:

我该怎么做?

您可以使用scipy.stats.gaussian_kde 创建密度估计函数。然后在 x-values 的数组上调用该函数以计算其最大值。

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

df = pd.DataFrame({'x': np.random.normal(0.001, 1, 1300).cumsum() + 30,
                   'hue': np.repeat(np.arange(0.08, 0.20001, 0.01), 100).round(2)})
g = sns.displot(df, x='x', hue='hue', palette='turbo', kind='kde', fill=True, height=6, aspect=1.5)
plt.show()

from scipy.stats import gaussian_kde
from matplotlib.cm import ScalarMappable

fig, ax = plt.subplots(figsize=(10, 6))
hues = df['hue'].unique()
num_hues = len(hues)
colors = sns.color_palette('turbo', num_hues)
xmin, xmax = df['x'].min(), df['x'].max()
xs = np.linspace(xmin, xmax, 500)
for hue, color in zip(hues, colors):
     data = df[df['hue'] == hue]['x'].values
     kde = gaussian_kde(data)
     mode_index = np.argmax(kde(xs))
     mode_x = xs[mode_index]
     sns.scatterplot(x=[hue], y=[mode_x], color=color, s=50, ax=ax)
cmap = sns.color_palette('turbo', as_cmap=True)
norm = plt.Normalize(hues.min(), hues.max())
plt.colorbar(ScalarMappable(cmap=cmap, norm=norm), ax=ax, ticks=hues)
plt.show()

这是另一种方法,提取 kde 曲线。它使用 kde 图的图例来获得曲线和色调值之间的对应关系。 sns.kdeplotsns.displot(kind='kde') 使用的 axes-level 函数。 fill=False 为曲线创建线而不是填充多边形,这样更容易提取值。 (ax1.fill_between 可以在第二次通过时填充曲线)。第二个图的 x 和 y 轴被切换以对齐两个图的 x-axes。

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

df = pd.DataFrame({'x': np.random.normal(0.007, 0.1, 1300).cumsum() + 30,
                   'hue': np.repeat(np.arange(0.08, 0.20001, 0.01), 100).round(2)})
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(12, 10), sharex=True)

sns.kdeplot(data=df, x='x', hue='hue', palette='turbo', fill=False, ax=ax1)

hues = [float(txt.get_text()) for txt in ax1.legend_.get_texts()]
ax2.set_yticks(hues)
ax2.set_ylabel('hue')
for hue, line in zip(hues, ax1.lines[::-1]):
     color = line.get_color()
     x = line.get_xdata()
     y = line.get_ydata()
     ax1.fill_between(x, y, color=color, alpha=0.3)
     mode_ind = np.argmax(y)
     mode_x = x[mode_ind]
     sns.scatterplot(x=[mode_x], y=hue, color=color, s=50, ax=ax2)

sns.despine()
plt.tight_layout()
plt.show()