Python:一个点中的seapoint点图和箱线图但在x轴上移动 [英] Python: seaborn pointplot and boxplot in one plot but shifted on the x-axis

查看:318
本文介绍了Python:一个点中的seapoint点图和箱线图但在x轴上移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在一个图中同时绘制箱线图和均值.到目前为止,使用以下几行代码,我的情节看起来像这样:

I want to plot both a boxplot and the mean in one figure. So far my plot looks like this using these lines of code:

sns.swarmplot(x="stimulus", y="data", data=spi_num.astype(np.float), edgecolor="black", linewidth=.9)
sns.boxplot(x="stimulus", y="data", data=spi_num.astype(np.float), saturation=1)
sns.pointplot(x="stimulus", y="data", data=spi_num.astype(np.float), linestyles='', scale=1, color='k', errwidth=1.5, capsize=0.2, markers='x')
sns.pointplot(x="stimulus", y="data", data=spi_num.astype(np.float), linestyles='--', scale=0.4, color='k', errwidth=0, capsize=0)
plt.ylabel("number of spikes")
plt.title("Median Number of Spikes");

我想将我的平均"x"标记向右移一点,以使误差线不会与箱线图中的晶须重叠.任何想法如何做到这一点?一个额外的问题:如何在该图中插入图例,以优雅地标明"x:均值,o:数据值"?

I would like to shift my mean 'x' markers a bit to the right so that the errorbars don't overlap with the whiskers from the boxplot. Any idea how to do that? A bonus question: how do I insert a legend in this plot saying "x: mean, o: data values" elegantly?

trial_vec    = np.tile(np.arange(16)+1, 10)     
stimulus_vec = np.repeat([-2., -1.75, -1., -0.75, -0.5,  0.5,  1.,  1.25,  1.75,  2.5 ], 16)                  
data_vec     = np.random.randint(0, 16, size=160)
spi_num      = pd.DataFrame({'trial': trial_vec, 'stimulus': stimulus_vec, 'data': data_vec}).astype('object')

推荐答案

为了平移绘图上的点,可以使用变换.在这种情况下,ScaledTranslation是有用的.不幸的是,seaborn不允许直接使用变换,也无法访问绘制的对象.因此,需要从轴获取绘制的对象(在本例中为PathCollection).如果要偏移的图是轴ax中的第一个图,我们可以简单地通过ax.collections[0]来获取它.然后我们可以通过.set_transform对其进行设置.

In order to shift points on a plot, one may use a transform; in this case a ScaledTranslation is useful. Unfortunately, seaborn does not allow to use the transform directly and does not give access to the plotted objects. Therefore one needs to get the plotted object (in this case the PathCollection) from the axes. If the plot to be offset is the first plot in the axes ax, we might simply get it via ax.collections[0]. Then we can set the transform to it via .set_transform.

fig, ax = plt.subplots()
sns.pointplot(... , ax=ax)
#produce transform with 5 points offset in x direction
offset = transforms.ScaledTranslation(5/72., 0, ax.figure.dpi_scale_trans)
trans = ax.collections[0].get_transform()
ax.collections[0].set_transform(trans + offset)

完整代码:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms


trial_vec    = np.tile(np.arange(16)+1, 10)     
stimulus_vec = np.repeat([-2., -1.75, -1., -0.75, -0.5,  0.5,  1.,  1.25,  1.75,  2.5 ], 16)
data_vec     = np.random.randint(0, 16, size=160)
spi_num      = pd.DataFrame({'trial': trial_vec, 
                             'stimulus': stimulus_vec, 'data': data_vec})

fig, ax = plt.subplots()

sns.pointplot(x="stimulus", y="data", data=spi_num, linestyles='', scale=1, 
              color='k', errwidth=1.5, capsize=0.2, markers='x', ax=ax)
#produce transform with 5 points offset in x direction
offset = transforms.ScaledTranslation(5/72., 0, ax.figure.dpi_scale_trans)
trans = ax.collections[0].get_transform()
ax.collections[0].set_transform(trans + offset)

sns.swarmplot(x="stimulus", y="data", data=spi_num, edgecolor="black", linewidth=.9, ax=ax)
sns.boxplot(x="stimulus", y="data", data=spi_num, saturation=1, ax=ax)
sns.pointplot(x="stimulus", y="data", data=spi_num, linestyles='--', scale=0.4, 
              color='k', errwidth=0, capsize=0, ax=ax)
plt.ylabel("number of spikes")
plt.title("Median Number of Spikes");

plt.show()

要同时移动线图,您需要对其散点(ax.collections[1])和图中的所有线(ax.lines)进行与上述相同的操作

To shift the lineplot as well, you would need to do the same as above with its scatter points (ax.collections[1]) and for all the lines in the plot (ax.lines)

sns.pointplot(x="stimulus", y="data", data=spi_num, linestyles='--', scale=0.4, 
              color='k', errwidth=0, capsize=0, ax=ax, gid="Nm")
# shift points of connecting line:
trans = ax.collections[1].get_transform()
ax.collections[1].set_transform(trans + offset)
# shift everything else:
for line in ax.lines:
    trans = line.get_transform()
    line.set_transform(trans + offset)

这篇关于Python:一个点中的seapoint点图和箱线图但在x轴上移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆