来自按级别分组的多索引 pandas 数据帧的子图
subplots from a multiindex pandas dataframe grouped by level
我如何根据多索引的一个级别从多索引 pandas DataFrame 中绘制多个图?
我有一个模型在不同场景下使用不同技术的结果,结果可能如下所示:
import numpy as np
import pandas as pd
df=pd.DataFrame(abs(np.random.randn(12,4)),columns=[2011,2012,2013,2014])
df['scenario']=['s1','s1','s1','s2','s2','s3','s3','s3','s3','s4','s4','s4']
df['technology'=['t1','t2','t5','t2','t6','t1','t3','t4','t5','t1','t3','t4']
dfg=df.groupby(['scenario','technology']).sum().transpose()
dfg 每年都会针对每种情况采用这些技术。我想为共享图例的每个场景创建一个子图。
如果我简单地使用参数 subplots=True,那么它会绘制所有可能的组合(12 个子图)
dfg.plot(kind='bar',stacked=True,subplots=True)
基于this response,我离我要找的东西更近了。
f,a=plt.subplots(2,2)
fig1=dfg['s1'].plot(kind='bar',ax=a[0,0])
fig2=dfg['s2'].plot(kind='bar',ax=a[0,1])
fig2=dfg['s3'].plot(kind='bar',ax=a[1,0])
fig2=dfg['s3'].plot(kind='bar',ax=a[1,1])
plt.tight_layout()
但结果并不理想,每个情节都有不同的图例......这使得阅读起来非常困难。必须有一种更简单的方法来从多索引数据帧中进行子图......谢谢!
EDIT1:Ted Petrou 使用 seaborn factorplot 提出了一个很好的解决方案,但我有两个问题。我已经定义了一个样式,我不想使用 seaborn 样式(一种解决方案是更改 seaborn 的参数)。另一个问题是我想使用堆叠条形图,这需要相当大的 extra tweaks。我有机会用 Matplotlib 做类似的事情吗?
在我看来,'tidy' 整理数据会更容易进行数据分析 - 让每一列代表一个变量。在这里,您将所有 4 年都表示在不同的列中。 Pandas 具有一种功能和一种方法,可以从宽(乱)的数据中生成长(整齐)的数据。您可以使用 df.stack
或 pd.melt(df)
来整理数据。然后你可以利用优秀的 seaborn 库,它需要整洁的数据来轻松绘制你想要的大部分内容。
整理数据
df1 = pd.melt(df, id_vars=['scenario', 'technology'], var_name='year')
print(df1.head())
scenario technology year value
0 s1 t1 2011 0.406830
1 s1 t2 2011 0.495418
2 s1 t5 2011 0.116925
3 s2 t2 2011 0.904891
4 s2 t6 2011 0.525101
使用 Seaborn
import seaborn as sns
sns.factorplot(x='year', y='value', hue='technology',
col='scenario', data=df1, kind='bar', col_wrap=2,
sharey=False)
我如何根据多索引的一个级别从多索引 pandas DataFrame 中绘制多个图?
我有一个模型在不同场景下使用不同技术的结果,结果可能如下所示:
import numpy as np
import pandas as pd
df=pd.DataFrame(abs(np.random.randn(12,4)),columns=[2011,2012,2013,2014])
df['scenario']=['s1','s1','s1','s2','s2','s3','s3','s3','s3','s4','s4','s4']
df['technology'=['t1','t2','t5','t2','t6','t1','t3','t4','t5','t1','t3','t4']
dfg=df.groupby(['scenario','technology']).sum().transpose()
dfg 每年都会针对每种情况采用这些技术。我想为共享图例的每个场景创建一个子图。
如果我简单地使用参数 subplots=True,那么它会绘制所有可能的组合(12 个子图)
dfg.plot(kind='bar',stacked=True,subplots=True)
基于this response,我离我要找的东西更近了。
f,a=plt.subplots(2,2)
fig1=dfg['s1'].plot(kind='bar',ax=a[0,0])
fig2=dfg['s2'].plot(kind='bar',ax=a[0,1])
fig2=dfg['s3'].plot(kind='bar',ax=a[1,0])
fig2=dfg['s3'].plot(kind='bar',ax=a[1,1])
plt.tight_layout()
但结果并不理想,每个情节都有不同的图例......这使得阅读起来非常困难。必须有一种更简单的方法来从多索引数据帧中进行子图......谢谢!
EDIT1:Ted Petrou 使用 seaborn factorplot 提出了一个很好的解决方案,但我有两个问题。我已经定义了一个样式,我不想使用 seaborn 样式(一种解决方案是更改 seaborn 的参数)。另一个问题是我想使用堆叠条形图,这需要相当大的 extra tweaks。我有机会用 Matplotlib 做类似的事情吗?
在我看来,'tidy' 整理数据会更容易进行数据分析 - 让每一列代表一个变量。在这里,您将所有 4 年都表示在不同的列中。 Pandas 具有一种功能和一种方法,可以从宽(乱)的数据中生成长(整齐)的数据。您可以使用 df.stack
或 pd.melt(df)
来整理数据。然后你可以利用优秀的 seaborn 库,它需要整洁的数据来轻松绘制你想要的大部分内容。
整理数据
df1 = pd.melt(df, id_vars=['scenario', 'technology'], var_name='year')
print(df1.head())
scenario technology year value
0 s1 t1 2011 0.406830
1 s1 t2 2011 0.495418
2 s1 t5 2011 0.116925
3 s2 t2 2011 0.904891
4 s2 t6 2011 0.525101
使用 Seaborn
import seaborn as sns
sns.factorplot(x='year', y='value', hue='technology',
col='scenario', data=df1, kind='bar', col_wrap=2,
sharey=False)