【问题标题】:Pandas+seaborn faceting with multidimensional dataframes带有多维数据框的 Pandas+seaborn 刻面
【发布时间】:2018-09-06 09:17:35
【问题描述】:

在 Python pandas 中,我需要从多维 DataFrame 做一个分面网格。 在ab 列中,我保存了标量值,它们表示实验的条件。 在 xy 列中,我有两个 numpy 数组。列x 是数据的x 轴,列y 是对应于f(x) 的函数的值。 显然xy 的元素数量相同。

我现在想做一个 facet grid,其中行和列指定条件,并在网格的每个单元格中,绘制 D 列与 D 列的值。

这可能是一个最小的工作示例:

import pandas as pd
d = [0]*4 # initialize a list with 4 elements
d[0] = {'x':[1,2,3],'y':[4,5,6],'a':1,'b':2} # then fill these elements
d[1] = {'x':[3,1,5],'y':[6,5,1],'a':0,'b':3}
d[2] = {'x':[3,1,5],'y':[6,5,1],'a':1,'b':3}
d[3] = {'x':[3,1,5],'y':[6,5,1],'a':0,'b':2}
pd.DataFrame(d) # create the pandas dataframe

如何使用现有的分面函数来解决按条件ab 分组的y vs x 绘图问题?

由于我需要将此函数应用于具有不同列名的通用数据集,因此我想避免使用硬编码的解决方案,而是看看是否可以将 seaborn FacetGrid 函数扩展到此类问题。

【问题讨论】:

    标签: python pandas seaborn facet


    【解决方案1】:

    我认为最好的方法是先拆分嵌套数组,然后使用 seaborn 创建一个 facet 网格。

    感谢这篇文章 (Split nested array values from Pandas Dataframe cell over multiple rows),我能够在您的数据框中拆分嵌套数组:

    unnested_lst = []
    for col in df.columns:
        unnested_lst.append(df[col].apply(pd.Series).stack())
    result = pd.concat(unnested_lst, axis=1, keys=df.columns).fillna(method='ffill')
    

    然后您可以使用以下代码制作分面网格:

    import seaborn as sbn
    fg = sbn.FacetGrid(result, row='b', col='a')
    fg.map(plt.scatter, "x", "y", color='blue')
    

    【讨论】:

    • 巧妙地使用pd.concat
    【解决方案2】:

    你需要一个长框架才能使用FacetGrid,所以最好的办法是分解列表,然后重新组合并应用:

    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    
    d = [0]*4
    d[0] = {'x':[1,2,3],'y':[4,5,6],'a':1,'b':2} # then fill these elements
    d[1] = {'x':[3,1,5],'y':[6,5,1],'a':0,'b':3}
    d[2] = {'x':[3,1,5],'y':[6,5,1],'a':1,'b':3}
    d[3] = {'x':[3,1,5],'y':[6,5,1],'a':0,'b':2}
    df = pd.DataFrame(d)
    
    df.set_index(['a','b'], inplace=True, drop=True)
    
    x_long = pd.melt(df['x'].apply(pd.Series).reset_index(),
                     id_vars=['a', 'b'], value_name='x')
    
    y_long = pd.melt(df['y'].apply(pd.Series).reset_index(),
                     id_vars=['a', 'b'], value_name='y')
    
    long_df = pd.merge(x_long, y_long).drop('variable', axis='columns')
    
    grid = sns.FacetGrid(long_df, row='a', col='b')
    grid.map(plt.scatter, 'x', 'y')
    plt.show()
    

    这将显示以下内容:

    【讨论】:

    • 零时间的好答案,我现在明白需要使用pd.melt的原因。
    【解决方案3】:

    我相信最好、最短和最容易理解的解决方案是定义一个恰当创建的lambda 函数。它以FacetGrid.map 方法指定的映射变量作为输入,并通过.values[0] 以numpy 数组的形式获取其值,因为它们是唯一的。

    import pandas as pd
    d = [0]*4 # initialize a list with 4 elements
    d[0] = {'x':[1,2,3],'y':[4,5,6],'a':1,'b':2} # then fill these elements
    d[1] = {'x':[3,1,5],'y':[6,5,1],'a':0,'b':3}
    d[2] = {'x':[3,1,5],'y':[6,5,1],'a':1,'b':3}
    d[3] = {'x':[3,1,5],'y':[6,5,1],'a':0,'b':2}
    df = pd.DataFrame(d) # create the pandas dataframe
    
    import seaborn as sns
    import matplotlib.pyplot as plt
    grid = sns.FacetGrid(df,row='a',col='b')
    grid.map(lambda _x,_y,**kwargs : plt.scatter(_x.values[0],_y.values[0]),'x','y')
    

    【讨论】:

      猜你喜欢
      • 2019-05-16
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      • 1970-01-01
      • 2020-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多