我想为一些数据绘制一个KDE,其数据涵盖了x值的大范围。因此,我想对x轴使用对数标度。为了绘图,我使用了seaborn和来自Plotting 2D Kernel Density Estimation with Python的解决方案,一旦我将xscale设置为对数,两者都失败了。当我事先取出我的x数据的对数时,一切看起来都很好,除了抽搐和标签仍然是线性的,实际值的对数作为标签。我可以使用以下方式手动更改抽搐:
labels = np.array(ax.get_xticks().tolist(), dtype=np.float64)
new_labels = [r'$10^{%.1f}$' % (labels[i]) for i in range(len(labels))]
ax.set_xticklabels(new_labels)
但在我看来,当我使用
时,看起来是错误的并且与轴标签(包括次要抽搐)没什么关系ax.set_xscale('log')
是否有更简单的方法用对数x数据绘制KDE?或者是否可以在不改变数据缩放的情况下更改标记或标注比例,以便我可以绘制x的对数值并在之后更改标签的缩放比例?
编辑: 我想要创建的情节如下所示: 两个右列是它应该看起来的样子。在那里我使用了已经应用了对数的x数据。不过,我不喜欢x轴上的标签。
当原始数据用于kde和所有其他绘图时,左列显示绘图,然后使用
更改刻度ax.set_xscale('log')
由于某种原因kde,看起来不应该看起来。这也不是错误数据的结果,因为如果使用对数数据它看起来很好。
编辑2: 代码的工作示例是
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
data = np.random.multivariate_normal((0, 0), [[0.8, 0.05], [0.05, 0.7]], 100)
x = np.power(10, data[:, 0])
y = data[:, 1]
fig, ax = plt.subplots(2, 1)
sns.kdeplot(data=np.log10(x), data2=y, ax=ax[0])
sns.kdeplot(data=x, data2=y, ax=ax[1])
ax[1].set_xscale('log')
plt.show()
ax[1]
绘图未正确显示(x轴反转),但一般行为与上述情况相同。我认为问题在于kde的带宽,这可能应该考虑对数x数据。
答案 0 :(得分:0)
我找到了一个适用于我的答案,并希望发布以防其他人遇到类似问题。
基于this帖子中接受的答案,我定义了一个函数,该函数首先将对数应用于x数据,并且在执行KDE之后,将x值转换回原始值。之后我可以简单地绘制轮廓并使用ax.set_xscale('log')
def logx_kde(x, y, xmin, xmax, ymin, ymax):
x = np.log10(x)
# Peform the kernel density estimate
xx, yy = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([xx.ravel(), yy.ravel()])
values = np.vstack([x, y])
kernel = st.gaussian_kde(values)
f = np.reshape(kernel(positions).T, xx.shape)
return np.power(10, xx), yy, f