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

时间:2015-10-02 07:58:57

标签: python python-2.7 pandas data-analysis seaborn

我使用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.

3 个答案:

答案 0 :(得分:3)

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

如果缺少的值很少且分散,则可以方便地使用dropna()。在其他情况下,我会选择用先前观察到的值(1)填充缺失值。甚至用内插值(2)填充缺失值。不过要小心!用填充或内插的观察值替换很多数据可能会严重中断您的数据集并导致非常错误的结论。

以下是使用您的摘要的示例...

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)')

enter image description here

(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)')

enter image description here

如您所见,不同的方法呈现两个截然不同的结果。希望对您有用。如果没有,那么让我知道,我会再看一遍。

答案 1 :(得分:2)

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

my_data <- rnorm(250, mean=1, sd=0.45)# unkonwn distribution parameters
fit <- fitdistr(my_data, densfun="normal")

答案 2 :(得分:0)

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

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

建议各种解决方法的地方,其中两个收藏夹(例如来自https://stackoverflow.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))