使用 seaborn 绘图时如何处理缺失值?

Posted

技术标签:

【中文标题】使用 seaborn 绘图时如何处理缺失值?【英文标题】:What to do with missing values when plotting with seaborn? 【发布时间】:2015-12-30 09:47:31 【问题描述】:

我使用 lambda 以下函数将缺失值替换为 NaN:

data = data.applymap(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)

,其中 data 是我正在处理的数据框。

之后使用seaborn,我尝试使用seaborn.distplot绘制它的一个属性,alcconsumption如下:

seaborn.distplot(data['alcconsumption'],hist=True,bins=100)
plt.xlabel('AlcoholConsumption')
plt.ylabel('Frequency(normalized 0->1)')

它给了我以下错误:

AttributeError: max must be larger than min in range parameter.

【问题讨论】:

为什么不在绘图前删除它们? 怎么样?我指的是哪个函数? data['alcconsumption'].dropna() @datavinci 如果我的建议有用,您会考虑将其标记为已接受的答案吗? 【参考方案1】:

我肯定会在您绘制数据之前处理缺失值。是否不使用dropna() 将完全取决于您的数据集的性质。 alcconsumption 是单个系列还是数据框的一部分?在后一种情况下,使用dropna() 也会删除其他列中的相应行。缺失值少还是多?它们是散布在你的系列中,还是倾向于成群出现?是否有理由相信您的数据集中存在趋势?

如果缺失值很少且分散,您可以轻松使用 dropna()。在其他情况下,我会选择用之前观察到的值 (1) 填充缺失值。甚至用插值 (2) 填充缺失值。但小心点!用填充或插值的观察值替换大量数据可能会严重中断您的数据集并导致非常错误的结论。

这里有一些使用你的 sn-p 的例子...

seaborn.distplot(data['alcconsumption'],hist=True,bins=100)
plt.xlabel('AlcoholConsumption')
plt.ylabel('Frequency(normalized 0->1)')

...在合成数据集上:

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

def sample(rows, names):
    ''' Function to create data sample with random returns

    Parameters
    ==========
    rows : number of rows in the dataframe
    names: list of names to represent assets

    Example
    =======

    >>> sample(rows = 2, names = ['A', 'B'])

                  A       B
    2017-01-01  0.0027  0.0075
    2017-01-02 -0.0050 -0.0024
    '''
    listVars= names
    rng = pd.date_range('1/1/2017', periods=rows, freq='D')
    df_temp = pd.DataFrame(np.random.randint(-100,100,size=(rows, len(listVars))), columns=listVars) 
    df_temp = df_temp.set_index(rng)


    return df_temp

df = sample(rows = 15, names = ['A', 'B'])
df['A'][8:12] = np.nan
df

输出:

            A   B
2017-01-01 -63.0  10
2017-01-02  49.0  79
2017-01-03 -55.0  59
2017-01-04  89.0  34
2017-01-05 -13.0 -80
2017-01-06  36.0  90
2017-01-07 -41.0  86
2017-01-08  10.0 -81
2017-01-09   NaN -61
2017-01-10   NaN -80
2017-01-11   NaN -39
2017-01-12   NaN  24
2017-01-13 -73.0 -25
2017-01-14 -40.0  86
2017-01-15  97.0  60

1。使用 pandas.DataFrame.fillna(method = ffill) 前向填充

ffill 将“向前填充值”,这意味着它将用上一行的值替换 nan

df = df['A'].fillna(axis=0, method='ffill')
sns.distplot(df, hist=True,bins=5)
plt.xlabel('AlcoholConsumption')
plt.ylabel('Frequency(normalized 0->1)')

2。对pandas.DataFrame.interpolate() 使用插值

根据不同的方法插值。时间插值适用于每日和更高分辨率的数据,以插值给定的间隔长度。

df['A'] = df['A'].interpolate(method = 'time')
sns.distplot(df['A'], hist=True,bins=5)
plt.xlabel('AlcoholConsumption')
plt.ylabel('Frequency(normalized 0->1)')

如您所见,不同的方法会呈现两种截然不同的结果。我希望这对你有用。如果没有,请告诉我,我会再看一遍。

【讨论】:

【参考方案2】:

这可能无法解决所提出的问题,但我使用以下代码进行检查

sns.heatmap(df.isnull(),yticklabels=False,cbar=False,cmap='viridis')

【讨论】:

请在此答案中添加更多上下文 - 此处不鼓励代码转储。 meta.***.com/questions/358727/…【参考方案3】:

您可以使用以下行来选择使用 seaborn 的分布图的非 NaN 值:

seaborn.distplot(data['alcconsumption'].notnull(),hist=True,bins=100)

【讨论】:

[displot] 从 1.11 版开始,seaborn 说:“此功能已弃用,将在未来版本中删除。” seaborn.pydata.org/generated/seaborn.distplot.html 不应该是seaborn.distplot(data[data['alcconsumption'].notnull()]['alcconsumption'],hist=True,bins=100) 吗?我相信data['alcconsumption'].notnull() 输出布尔值【参考方案4】:

这是 matplotlib/pylab 直方图的一个已知问题!

参见例如https://github.com/matplotlib/matplotlib/issues/6483

建议了各种解决方法,其中两个最喜欢的(例如来自https://***.com/a/19090183/1021819)是:

import numpy as np
nbins=100
A=data['alcconsumption']
Anan=A[~np.isnan(A)] # Remove the NaNs

seaborn.distplot(Anan,hist=True,bins=nbins)

或者,指定 bin 边缘(在这种情况下,无论如何都要使用 Anan...):

Amin=min(Anan)
Amax=max(Anan)
seaborn.distplot(A,hist=True,bins=np.linspace(Amin,Amax,nbins))

【讨论】:

以上是关于使用 seaborn 绘图时如何处理缺失值?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理python scikit NMF中的缺失值

如何处理 Python 中应该缺失的缺失值(不应插入 NaN)?

机器学习决策树为什么对缺失值不敏感,如何处理缺失值?

如何处理 Matlab 中 Kruskal-Wallis 测试中的缺失值?

2020-08-05--Pandas-03--缺失值处理

如何处理DataFrame中缺失项