首页 文章

Seaborn配对图和NaN值

提问于
浏览 35
4

我试图理解为什么会失败,即使文档说:

dropna:boolean,optional绘制前从数据中删除缺失值 .

from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
sns.__version__
# '0.7.dev'
# generate an example DataFrame
a = pd.DataFrame(data={
    'a': np.random.normal(size=(100,)),
    'b': np.random.lognormal(size=(100,)),
    'c': np.random.exponential(size=(100,))})
sns.pairplot(a) # this works as expected
# snip
b = a.copy()
b.iloc[5,2] = np.nan # replace one value in col 'c' by a NaN
sns.pairplot(b) # this fails with error 
                # "AttributeError: max must be larger than min in range parameter."
                # in histogram(a, bins, range, normed, weights, density)"
> sns.pairplot(b, dropna=True) # same error as above

3 回答

  • 3

    一个坏死的东西 - 但是当我今天破解了这个答案时,我认为可能值得分享 . 我无法在网络上的其他地方找到此解决方案...如果Seaborn ignoreNa关键字对您的数据不起作用,并且您不想删除所有具有任何NaN的行 . 这应该适合你 .

    所有这一切都在Seaborn 0.9中,pandas为0.23.4,假设数据框(df)有j行(样本),有n列(属性) .

    解决了Seaborn无法应对NaN阵列传递给它的问题;特别是当你想确保你保留一行时,因为它有其他有用的数据,是基于使用一个函数拦截成对列,然后传递给 PairGrid 进行绘图 .

    可以将函数传递到网格扇区以执行每个子图的操作 . 一个简单的例子是计算和注释每个图上的列对(子图)的RMSE:

    def rmse(x,y, **kwargs):
        rmse = math.sqrt(skm.mean_squared_error(x, y))
    
        label = 'RMSE = ' + str(round(rmse, 2))  
        ax = plt.gca()
        ax.annotate(label, xy = (0.1, 0.95), size = 20, xycoords = ax.transAxes)
    
    grid = grid.map_upper(rmse)
    

    因此,通过编写Seaborn可以作为数据绘图参数的函数,当 grid.map_ 迭代主数据帧时,它会在列对的基础上丢弃NaN,我们可以最小化每个样本(行)的数据丢失 . 这是因为连续的一个NaN不会导致整个行丢失所有子图 . 但只是该特定列对的子图将排除给定的行 .

    以下函数执行成对的NaN drop,返回seaborn的两个系列,然后用matplotlibs散点图在轴上绘图:

    df = [YOUR DF HERE]
    
    def col_nan_scatter(x,y, **kwargs):
        df = pd.DataFrame({'x':x[:],'y':y[:]})
        df = df.dropna()
        x = df['x']
        y = df['y']
        plt.gca()
        plt.scatter(x,y)  
    
    cols = df.columns
    grid = sns.PairGrid(data= df, vars = cols, height = 4)
    grid = grid.map_upper(col_nan_scatter)
    

    使用seaborn绘图可以完成相同的操作(例如,只有x值):

    def col_nan_kde_histo(x, **kwargs):
        df = pd.DataFrame({'x':x[:]})
        df = df.dropna()
        x = df['x']
        plt.gca()
        sns.kdeplot(x)
    
    cols = df.columns
    grid = sns.PairGrid(data= df, vars = cols, height = 4)
    grid = grid.map_upper(col_nan_scatter)
    grid = grid.map_upper(col_nan_kde_histo)
    
  • 2

    我一般都解决了这个问题,但至少它解决了我的问题 .

    尝试绘制直方图时出现问题 . 但是,看起来 kde 对于丢失数据更加健壮 . 因此,尽管 NaN 位于数据帧的中间,但这仍然有效:

    from matplotlib import pyplot as plt
    import numpy as np
    import pandas as pd
    import seaborn as sns
    sns.__version__
    # '0.7.dev'
    # generate an example DataFrame
    a = pd.DataFrame(data={
        'a': np.random.normal(size=(100,)),
        'b': np.random.lognormal(size=(100,)),
        'c': np.random.exponential(size=(100,))})
    a.iloc[5,2] = np.nan # replace one value in col 'c' by a NaN
    sns.pairplot(a, diag_kind='kde')
    
  • 0

    当你直接使用数据时,即

    sns.pairplot(b) #Same as sns.pairplot(b, x_vars=['a','b','c'] , y_vars=['a','b','c'],dropna=True)
    

    您正在绘制DataFrame中的所有列,然后确保没有:所有列中的行都相同 .

    sns.pairplot(b, x_vars=['a','c'] , y_vars=['a','b','c'],dropna=True)
    

    在这种情况下,它工作正常,但图表中将有一个微小的差异,以删除'NaN值' .

    那么,如果你想用整个数据绘图那么: -

    • 必须使用“fillna()”替换空值,

    必须删除

    • 或包含'nan values'的整行
    b = b.drop(b.index[5])
    sns.pairplot(b)
    

    pairplot for dropped values

相关问题