在Python pandas
中,我需要从多维DataFrame
进行多面网格处理。
在a
和b
列中,我持有表示实验条件的标量值。
在列x
和y
中,我有两个numpy数组。 x
列是数据的x轴,y
列是与f(x)
对应的函数的值。
显然,x
和y
具有相同数量的元素。
我现在想做一个方面网格,其中行和列指定条件,并在网格的每个单元格中绘制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
如何使用已有的构面功能来解决按条件y vs x
和a
分组的b
绘制问题?
由于我需要将此函数应用于具有不同列名的常规数据集,因此我想避免求助于硬编码的解决方案,而是想知道是否有可能将seaborn FacetGrid
函数扩展到此类问题
答案 0 :(得分:2)
我认为最好的方法是先拆分嵌套数组,然后创建带有Seaborn的构面网格。
感谢这篇文章(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')
答案 1 :(得分:1)
您需要一个长框才能使用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()
答案 2 :(得分:0)
我认为最好,最短和最易理解的解决方案是定义一个适当创建的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')