在 python 中将 1 个变量与多个变量进行比较时,如何在 seaborn 的因子图中将条形图彼此靠近?
How to put bars close to each other in a seaborn's factorplot when comparing 1 variable against many, in python?
我想绘制一个图来比较一个变量 (Fp1) 与其他 5 个变量。
我怎样才能让酒吧加入?我怎样才能摆脱他们之间的 space ?有办法吗?
数据框:
raw_data = {'Max_Acc': [90.71, 87.98, 92.62, 78.93, 73.69, 73.66, 72.29,
92.62, 94.17, 92.62, 83.81, 79.76, 74.40, 72.38],
'Stage': ['AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL',
'AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL'],
'Elec': ['Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1',
'C4', 'T3', 'Fp1', 'P4', 'Fp2', 'Fz', 'Fz']}
df_m=pd.DataFrame(raw_data, columns = ['Max_Acc', 'Stage', 'Elec'])
制作剧情的代码:
#Seaborn
sns.set(style="white")
g = sns.factorplot(x="Stage", y="Mean_Acc", hue='Clf', data=df, size=4, aspect=3, kind="bar",
legend=False)
g.set(ylim=(0, 120))
g.despine(right=False)
g.set_xlabels("")
g.set_ylabels("")
g.set_yticklabels("")
mylegend=plt.legend(bbox_to_anchor=(0., 1.1, 1., .102), prop ={'size':10}, loc=10, ncol=8, #left, bottom, width,
title=r'BEST STAGE AFTER OPTIMIZATION') #height, loc='center'
mylegend.get_title().set_fontsize('24')
ax=g.ax
def annotateBars(row, ax=ax):
for p in ax.patches:
ax.annotate("%.2f" % p.get_height(), (p.get_x() + p.get_width() / 2., p.get_height()),
ha='center', va='center', fontsize=11, color='gray', rotation=90, xytext=(0, 20),
textcoords='offset points')
plot = df_m.apply(annotateBars, ax=ax, axis=1)
剧情:
编辑
所以我在阅读答案后做了一些改进。但是我怎样才能使图例中的颜色与条形图中的颜色相匹配呢?我只有2个颜色,不过应该是6个。
编辑:使用相同的代码构成答案
编辑:
所以我升级了Matplotlib并添加了注释条形图的代码
因子图为给定 hue
参数的列中的每个唯一项目保留了条形子组中的一个位置。因此,您可以引入一个只有两个不同值的新列。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn.apionly as sns
raw_data = {'Max_Acc': [90.71, 87.98, 92.62, 78.93, 73.69, 73.66, 72.29,
92.62, 94.17, 92.62, 83.81, 79.76, 74.40, 72.38],
'Stage': ['AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL',
'AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL'],
'Elec': ['Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1',
'C4', 'T3', 'Fp1', 'P4', 'Fp2', 'Fz', 'Fz']}
df_m=pd.DataFrame(raw_data, columns = ['Max_Acc', 'Stage', 'Elec'])
df_m["hue"] = np.arange(0,len(df_m)) // (len(df_m)//2)
g = sns.factorplot(x="Stage", y="Max_Acc", hue="hue", data=df_m, size=4,
aspect=3, kind="bar", legend=False)
plt.show()
然后您需要使用 matplotlib 进行大量调整才能恢复颜色。
在这一点上你可能决定无论如何使用 matplotlib 条形图。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
raw_data = {'Max_Acc': [90.71, 87.98, 92.62, 78.93, 73.69, 73.66, 72.29,
92.62, 94.17, 92.62, 83.81, 79.76, 74.40, 72.38],
'Stage': ['AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL',
'AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL'],
'Elec': ['Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1',
'C4', 'T3', 'Fp1', 'P4', 'Fp2', 'Fz', 'Fz']}
df_m=pd.DataFrame(raw_data)
uelec, uind = np.unique(df_m["Elec"], return_inverse=1)
cmap = plt.cm.get_cmap("Set1")
fig, ax=plt.subplots()
l = len(df_m)
pos = np.arange(0,l) % (l//2) + (np.arange(0,l)//(l//2)-1)*0.4
ax.bar(pos, df_m["Max_Acc"], width=0.4, align="edge", ec="k", color=cmap(uind) )
handles=[plt.Rectangle((0,0),1,1, color=cmap(i), ec="k") for i in range(len(uelec))]
ax.legend(handles=handles, labels=list(uelec),
prop ={'size':10}, loc=9, ncol=8,
title=r'BEST STAGE AFTER OPTIMIZATION')
ax.set_xticks(range(l//2))
ax.set_xticklabels(df_m["Stage"][:l//2])
ax.set_ylim(0, 120)
plt.show()
要从 seaborn 调色板获取颜色,您可以使用
palette = sns.color_palette()
colors= [ palette[i] for i in uind]
...
ax.bar(..., color=colors)
...
handles=[plt.Rectangle((0,0),1,1, color=palette[i], ec="k") for i in range(len(uelec))]
只有当您没有为每个组和每个色调设置值时才会出现此问题。您可以使用 dodge=False
最小化条形之间的间隙
When you plot with dodge=False 和
When you plot without dodge=False
如果您还想添加条形值,则需要根据色调设置高度。
否则会报错 "ValueError: posx and posy should be finite values"
for p in ax.patches:
if float(p.get_height()) > 0:
height = p.get_height()
ax.text(p.get_x()+p.get_width()/2., height + 0.1,height ,ha="center")
else:
height = .00000001
我想绘制一个图来比较一个变量 (Fp1) 与其他 5 个变量。 我怎样才能让酒吧加入?我怎样才能摆脱他们之间的 space ?有办法吗?
数据框:
raw_data = {'Max_Acc': [90.71, 87.98, 92.62, 78.93, 73.69, 73.66, 72.29,
92.62, 94.17, 92.62, 83.81, 79.76, 74.40, 72.38],
'Stage': ['AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL',
'AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL'],
'Elec': ['Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1',
'C4', 'T3', 'Fp1', 'P4', 'Fp2', 'Fz', 'Fz']}
df_m=pd.DataFrame(raw_data, columns = ['Max_Acc', 'Stage', 'Elec'])
制作剧情的代码:
#Seaborn
sns.set(style="white")
g = sns.factorplot(x="Stage", y="Mean_Acc", hue='Clf', data=df, size=4, aspect=3, kind="bar",
legend=False)
g.set(ylim=(0, 120))
g.despine(right=False)
g.set_xlabels("")
g.set_ylabels("")
g.set_yticklabels("")
mylegend=plt.legend(bbox_to_anchor=(0., 1.1, 1., .102), prop ={'size':10}, loc=10, ncol=8, #left, bottom, width,
title=r'BEST STAGE AFTER OPTIMIZATION') #height, loc='center'
mylegend.get_title().set_fontsize('24')
ax=g.ax
def annotateBars(row, ax=ax):
for p in ax.patches:
ax.annotate("%.2f" % p.get_height(), (p.get_x() + p.get_width() / 2., p.get_height()),
ha='center', va='center', fontsize=11, color='gray', rotation=90, xytext=(0, 20),
textcoords='offset points')
plot = df_m.apply(annotateBars, ax=ax, axis=1)
剧情:
编辑 所以我在阅读答案后做了一些改进。但是我怎样才能使图例中的颜色与条形图中的颜色相匹配呢?我只有2个颜色,不过应该是6个。
编辑:使用相同的代码构成答案
编辑:
所以我升级了Matplotlib并添加了注释条形图的代码
因子图为给定 hue
参数的列中的每个唯一项目保留了条形子组中的一个位置。因此,您可以引入一个只有两个不同值的新列。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn.apionly as sns
raw_data = {'Max_Acc': [90.71, 87.98, 92.62, 78.93, 73.69, 73.66, 72.29,
92.62, 94.17, 92.62, 83.81, 79.76, 74.40, 72.38],
'Stage': ['AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL',
'AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL'],
'Elec': ['Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1',
'C4', 'T3', 'Fp1', 'P4', 'Fp2', 'Fz', 'Fz']}
df_m=pd.DataFrame(raw_data, columns = ['Max_Acc', 'Stage', 'Elec'])
df_m["hue"] = np.arange(0,len(df_m)) // (len(df_m)//2)
g = sns.factorplot(x="Stage", y="Max_Acc", hue="hue", data=df_m, size=4,
aspect=3, kind="bar", legend=False)
plt.show()
然后您需要使用 matplotlib 进行大量调整才能恢复颜色。
在这一点上你可能决定无论如何使用 matplotlib 条形图。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
raw_data = {'Max_Acc': [90.71, 87.98, 92.62, 78.93, 73.69, 73.66, 72.29,
92.62, 94.17, 92.62, 83.81, 79.76, 74.40, 72.38],
'Stage': ['AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL',
'AWA', 'Rem', 'S1', 'S2', 'SWS', 'SX', 'ALL'],
'Elec': ['Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1', 'Fp1',
'C4', 'T3', 'Fp1', 'P4', 'Fp2', 'Fz', 'Fz']}
df_m=pd.DataFrame(raw_data)
uelec, uind = np.unique(df_m["Elec"], return_inverse=1)
cmap = plt.cm.get_cmap("Set1")
fig, ax=plt.subplots()
l = len(df_m)
pos = np.arange(0,l) % (l//2) + (np.arange(0,l)//(l//2)-1)*0.4
ax.bar(pos, df_m["Max_Acc"], width=0.4, align="edge", ec="k", color=cmap(uind) )
handles=[plt.Rectangle((0,0),1,1, color=cmap(i), ec="k") for i in range(len(uelec))]
ax.legend(handles=handles, labels=list(uelec),
prop ={'size':10}, loc=9, ncol=8,
title=r'BEST STAGE AFTER OPTIMIZATION')
ax.set_xticks(range(l//2))
ax.set_xticklabels(df_m["Stage"][:l//2])
ax.set_ylim(0, 120)
plt.show()
要从 seaborn 调色板获取颜色,您可以使用
palette = sns.color_palette()
colors= [ palette[i] for i in uind]
...
ax.bar(..., color=colors)
...
handles=[plt.Rectangle((0,0),1,1, color=palette[i], ec="k") for i in range(len(uelec))]
只有当您没有为每个组和每个色调设置值时才会出现此问题。您可以使用 dodge=False
最小化条形之间的间隙When you plot with dodge=False 和 When you plot without dodge=False 如果您还想添加条形值,则需要根据色调设置高度。 否则会报错 "ValueError: posx and posy should be finite values"
for p in ax.patches:
if float(p.get_height()) > 0:
height = p.get_height()
ax.text(p.get_x()+p.get_width()/2., height + 0.1,height ,ha="center")
else:
height = .00000001