【问题标题】:Replicate distplot with rug without histogram用没有直方图的地毯复制 distplot
【发布时间】:2021-08-16 13:56:04
【问题描述】:

当我浏览在线教程和\或一般文章时,当我遇到一个使用 Seaborn distplot 图我使用 histplot 或 displot 重新创建它。

我这样做是因为 distplot 已被弃用,我想使用更新的标准重新编写代码。

我正在浏览这篇文章:https://www.kite.com/blog/python/data-analysis-visualization-python/

并且有一个部分使用 distplot,其输出我无法复制。

这是我要复制的代码部分:

col_names = ['StrengthFactor', 'PriceReg', 'ReleaseYear', 'ItemCount', 'LowUserPrice', 'LowNetPrice']
fig, ax = plt.subplots(len(col_names), figsize=(8, 40))
for i, col_val in enumerate(col_names):
    x = sales_data_hist[col_val][:1000]
    sns.distplot(x, ax=ax[i], rug=True, hist=False)
    outliers = x[percentile_based_outlier(x)]
    ax[i].plot(outliers, np.zeros_like(outliers), 'ro', clip_on=False)

    ax[i].set_title('Outlier detection - {}'.format(col_val), fontsize=10)
    ax[i].set_xlabel(col_val, fontsize=8)

plt.show()

不再使用 distplot 本身和轴变量。代码现在运行。

简而言之,我所要做的就是在不使用已弃用代码的情况下复制上述代码的精确输出(地毯图、代表已删除值的红点等)。

我尝试了 displot 和 histplot 的各种组合,但我无法以任何其他方式获得完全相同的输出。

【问题讨论】:

  • 看来displot 应该能够复制这个。为了避免其他人重复您的努力,您已经尝试过什么,它与原始输出有何不同?
  • 我最接近的是:sns.displot(x, ax=ax[i], rug=True) 我得到了地毯,但它是直方图,而不是 kde 图,因为我使用的是 displot,所以我根本不明白。代表已删除值的红点消失了,我无法弄清楚如何在不完全破坏输出的情况下摆脱轴选项。 Histplot 没有地毯选项。
  • 使用上面的行,我得到了这些警告(并且我没有复制我的问题中发布的代码):C:\Users\Mark\AppData\Local\Programs\Python\Python38\lib\site-packages\seaborn\distributions.py:2164: UserWarning: `displot` is a figure-level function and does not accept the ax= paramter. You may wish to try histplot. warnings.warn(msg, UserWarning)
  • 是的,文档状态 displot 是图形级函数,而不是轴级函数,因此您无法告诉它要在哪些轴上绘图。我相信你可以改为使用kdeplot()rugplot() 来获得你想要的结果(我认为这就是displot 在幕后所做的)。此外,如果您想继续使用displot,可以使用kind='kde' 来获取kde 图而不是直方图。

标签: python matplotlib seaborn


【解决方案1】:

sns.kdeplot() 函数显示distplot 中可用的kde 曲线。 (实际上,distplot 只是在内部调用kdeplot)。同样,还有sns.rugplot() 来展示地毯。

这是一个更容易复制鸢尾花数据集的示例:

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

def percentile_based_outlier(data, threshold=95):
    diff = (100 - threshold) / 2
    minval, maxval = np.percentile(data, [diff, 100 - diff])
    return (data < minval) | (data > maxval)

iris = sns.load_dataset('iris')
col_names = [col for col in iris.columns if iris[col].dtype == 'float64']  # the numerical columns
fig, axs = plt.subplots(len(col_names), figsize=(5, 12))
for ax, col_val in zip(axs, col_names):
    x = iris[col_val]
    sns.kdeplot(x, ax=ax)
    sns.rugplot(x, ax=ax, color='C0')
    outliers = x[percentile_based_outlier(x)]
    ax.plot(outliers, np.zeros_like(outliers), 'ro', clip_on=False)

    ax.set_title(f'Outlier detection - {col_val}', fontsize=10)
    ax.set_xlabel('')  # ax[i].set_xlabel(col_val, fontsize=8)
plt.tight_layout()
plt.show()

要使用displot,可以通过pd.melt() 将数据帧转换为"long form"。可以通过g.map_dataframe(...) 调用的自定义函数添加异常值:

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

def percentile_based_outlier(data, threshold=95):
    diff = (100 - threshold) / 2
    minval, maxval = np.percentile(data, [diff, 100 - diff])
    return (data < minval) | (data > maxval)

def show_outliers(data, color):
    col_name = data['variable'].values[0]
    x = data['value'].to_numpy()
    outliers = x[percentile_based_outlier(x)]
    plt.plot(outliers, np.zeros_like(outliers), 'ro', clip_on=False)
    plt.xlabel('')

iris = sns.load_dataset('iris')
col_names = [col for col in iris.columns if iris[col].dtype == 'float64']  # the numerical columns
iris_long = iris.melt(value_vars=col_names)
g = sns.displot(data=iris_long, x='value', kind='kde', rug=True, row='variable',
                height=2.2, aspect=3,
                facet_kws={'sharey': False, 'sharex': False})
g.map_dataframe(show_outliers)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    相关资源
    最近更新 更多