如何在Seaborn中对齐KDE图和条形图?
我在调整Seaborn的KDE图时遇到了一些麻烦,想把它和我的条形图对齐。虽然我尝试了很多方法,比如修改bw_adjust参数和手动缩放KDE图,但还是没能达到想要的效果。
我的目标是为数据框中的一列绘制KDE图和条形图,以便可视化数据分布,同时也能看到数据点与KDE的关系。条形图还用不同的颜色来分类数据。
首先,如果我单独绘制条形图,代码如下:
sns.stripplot(data=df, x="values", hue="category")
然后,如果我单独绘制KDE图,代码如下:
sns.kdeplot(data=df, x="values", ax=ax)
但是,当我尝试把两者结合在一起时,代码如下:
fig, ax = plt.subplots(figsize=(16, 8))
sns.stripplot(data=df, x="values", hue="category")
sns.kdeplot(data=df, x="values", ax=ax)
奇怪的是,当KDE图和条形图一起绘制时,KDE图竟然变成了倒置的,我不太明白为什么会这样。所以我有两个问题想要解决:
- 把KDE图倒置回来,让它看起来像单独绘制时的样子。
- 正确缩放KDE图(或条形图),让数据点能和KDE图很好地结合在一起。
首先,我尝试在seaborn的stripplot和kdeplot函数中更改一些参数,代码如下:
sns.stripplot(data=df, x="values", hue="category", jitter=0.1, dodge=True, ax=ax)
sns.kdeplot(data=df, x="values", ax=ax, bw_adjust=-1)
看起来把bw_adjust设置为负数解决了第一个问题,结果如下(虽然我不太明白为什么这样有效):
不过,条形图的数据点仍然没有很好地表示出来,我不确定如何正确缩放KDE图,以便与条形图的数据更好地匹配。
所以,为了解决这个问题,我尝试手动绘制KDE图(不使用seaborn):
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from scipy.stats import gaussian_kde
df = pd.read_csv("inputs/desired_data.csv")
fig, ax = plt.subplots(figsize=(16, 8))
# Strip plot
sns.stripplot(data=df, x="values", hue="category", jitter=0.1, dodge=True, ax=ax)
# Computing KDE manually
x = df["values"].values
kde = gaussian_kde(x, bw_method=1)
x_grid = np.linspace(x.min(), x.max(), 1000)
y = kde.evaluate(x_grid)
# Normalize and scale the KDE plot
y_scaled = y / y.max() # Example normalization, adjust as needed
# Plot the scaled KDE
ax.plot(x_grid, y_scaled, color='blue')
这样在可视化数据点方面效果更好。但是,KDE图又变成了倒置的。如果我把bw_method=1
改成bw_method=-1
,在kde = gaussian_kde(x, bw_method=1)
中,我得到的图是这样的:
1 个回答
你想要画一个有点特别的图。stripplot
是把y轴翻转了,并且把范围设置在 -0.5
到 0.5
之间。而 kdeplot
则把y轴的最小值设置为0(这样它就“坐”在x轴上),而且它的高度是为了让曲线下面的面积标准化为 1
。
最简单的方法是使用双轴。把 kdeplot
画在原来的轴上,这样左边的y轴就会显示 kdeplot
的高度。stripplot
可以放在双轴上,y轴是独立的。
下面是一些示例代码:
import seaborn as sns
import matplotlib.pyplot as plt
iris = sns.load_dataset('iris')
fig, ax = plt.subplots()
sns.kdeplot(iris, x='sepal_width', ax=ax)
ax2 = ax.twinx()
sns.stripplot(iris, x='sepal_width', hue='species', ax=ax2, palette='turbo', dodge=True)
plt.tight_layout()
plt.show()