【问题标题】:How to change the position of a single swarm group如何改变单个swarm组的位置
【发布时间】:2019-11-01 10:36:47
【问题描述】:

我正在绘制一个分组条形图,在该条形图上叠加一个 swarmplot 和误差条。其中一个组只有一个条形图,我想在分配给这组条形图的位置中间出现(带有群体和误差条)。

我设法移动了 bar 和 errorbar,但不知道如何移动 swarm。

这是我的代码:

import seaborn as sns
import matplotlib.pyplot as plt
mypallet = sns.color_palette([(190/256,7/256, 18/256),(127/256, 127/256, 127/256)])
import itertools
import numpy as np

plt.rcParams['figure.figsize'] = 7, 5
tips = sns.load_dataset("tips")
tips[(tips.day=='Thur') & (tips.sex=='Female') ] = np.nan
print(sns.__version__)
print(tips.head())
# Bigger than normal fonts
sns.set(font_scale=1.5)

ax = sns.swarmplot(x="day", y="total_bill", hue="sex",
                 data=tips, split=True, color='k')
ax = sns.barplot(x="day", y="total_bill", hue="sex",
                 data=tips, capsize=0.1, alpha=0.8,
                 errwidth=1.25, ci=None, palette=mypallet)
xcentres = [0.2, 1, 2, 3]
delt = 0.2
xneg = [x-delt for x in xcentres]
xpos = [x+delt for x in xcentres]
xvals = xneg + xpos
xvals.sort()
yvals = tips.groupby(["day", "sex"]).mean().total_bill
yerr = tips.groupby(["day", "sex"]).std().total_bill

(_, caps, _)=ax.errorbar(x=xvals, y=yvals, yerr=yerr, capsize=4,
                         ecolor="red", elinewidth=1.25, fmt='none')
for cap in caps:
    cap.set_markeredgewidth(2)

handles, labels = ax.get_legend_handles_labels()
l = ax.legend(handles[0:2], labels[0:2]) # changed based on https://stackoverflow.com/a/42768387/8508004
#sns.ax.ylim([0,60]) #original
ax.set_ylim([0,60]) # adapted from https://stackoverflow.com/a/49049501/8508004 and change to legend
ax.set_ylabel("Out-of-sample R2") # based on https://stackoverflow.com/a/46235777/8508004
ax.set_xlabel("") # based on https://stackoverflow.com/a/46235777/8508004

for i, bar in enumerate(ax.patches):
    hatch = '///'
    bar.set_hatch(hatch)
    bar.set_x(bar.get_x() + bar.get_width()/2)
    break

我希望左侧栏的群与栏的中间位置对齐。

【问题讨论】:

    标签: python matplotlib seaborn swarmplot


    【解决方案1】:

    让我们使用matplotlib.collections set_offsets:

    import seaborn as sns
    import matplotlib.pyplot as plt
    mypallet = sns.color_palette([(190/256,7/256, 18/256),(127/256, 127/256, 127/256)])
    import itertools
    import numpy as np
    
    plt.rcParams['figure.figsize'] = 7, 5
    tips = sns.load_dataset("tips")
    tips[(tips.day=='Thur') & (tips.sex=='Female') ] = np.nan
    print(sns.__version__)
    print(tips.head())
    # Bigger than normal fonts
    sns.set(font_scale=1.5)
    
    ax = sns.swarmplot(x="day", y="total_bill", hue="sex",
                     data=tips, dodge=True, color='k')
    
    #get first patchcollection
    c0 = ax.get_children()[0]
    x,y = np.array(c0.get_offsets()).T
    #Add .2 to x values
    xnew=x+.2
    offsets = list(zip(xnew,y))
    #set newoffsets
    c0.set_offsets(offsets)
    
    ax = sns.barplot(x="day", y="total_bill", hue="sex",
                     data=tips, capsize=0.1, alpha=0.8,
                     errwidth=1.25, ci=None, palette=mypallet)
    xcentres = [0.2, 1, 2, 3]
    delt = 0.2
    xneg = [x-delt for x in xcentres]
    xpos = [x+delt for x in xcentres]
    xvals = xneg + xpos
    xvals.sort()
    yvals = tips.groupby(["day", "sex"]).mean().total_bill
    yerr = tips.groupby(["day", "sex"]).std().total_bill
    
    (_, caps, _)=ax.errorbar(x=xvals, y=yvals, yerr=yerr, capsize=4,
                             ecolor="red", elinewidth=1.25, fmt='none')
    for cap in caps:
        cap.set_markeredgewidth(2)
    
    
    handles, labels = ax.get_legend_handles_labels()
    l = ax.legend(handles[0:2], labels[0:2]) # changed based on https://stackoverflow.com/a/42768387/8508004
    #sns.ax.ylim([0,60]) #original
    ax.set_ylim([0,60]) # adapted from https://stackoverflow.com/a/49049501/8508004 and change to legend
    ax.set_ylabel("Out-of-sample R2") # based on https://stackoverflow.com/a/46235777/8508004
    ax.set_xlabel("") # based on https://stackoverflow.com/a/46235777/8508004
    
    for i, bar in enumerate(ax.patches):
        hatch = '///'
        bar.set_hatch(hatch)
        bar.set_x(bar.get_x() + bar.get_width()/2)
        break
    

    输出:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-11
      • 2017-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-22
      • 2019-03-31
      相关资源
      最近更新 更多