在 Matplotlib 中使用对数 x 数据绘制 KDE

Plotting KDE with logarithmic x-data in Matplotlib

我想为一些数据绘制一个 KDE,其中数据的 x 值范围很大。因此我想对 x 轴使用对数刻度。为了绘图,我使用了 seaborn 和来自 的解决方案,一旦我将 xscale 设置为对数,这两者都会失败。当我事先取 x 数据的对数时,一切看起来都很好,除了 tic 和 ticlabels 仍然与作为标签的实际值的对数成线性关系。我可以使用类似以下内容手动更改抽动:

labels = np.array(ax.get_xticks().tolist(), dtype=np.float64)
new_labels = [r'^{%.1f}$' % (labels[i]) for i in range(len(labels))]
ax.set_xticklabels(new_labels)

但在我看来,这看起来是错误的,并且当我只是使用

ax.set_xscale('log')

有没有更简单的方法来绘制具有对数 x 数据的 KDE?或者是否可以只更改 tic- 或标签比例而不更改数据的比例,这样我就可以绘制 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 数据。

我找到了一个适合我的答案,并想 post 以防其他人遇到类似问题。 根据 post 接受的答案,我定义了一个函数,该函数首先将对数应用于 x 数据,并在执行 KDE 后,将 x 值转换回原始值。之后我可以简单地绘制轮廓并使用 ax.set_xscale('log')

import numpy as np
import scipy.stats as st

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