简体   繁体   English

Python:seaborn pointplot和boxplot在一个图中,但在x轴上移位

[英]Python: seaborn pointplot and boxplot in one plot but shifted on the x-axis

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");

在此输入图像描述

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. 我想将我的平均'x'标记向右移动一点,以便错误条不与箱图中的胡须重叠。 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? 一个额外的问题:如何在这个情节中插入一个图例,说“x:mean,o:data values”?


Build my dataframe 构建我的数据帧

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')

In order to shift points on a plot, one may use a transform; 为了在图上移动点,可以使用变换; in this case a ScaledTranslation is useful. 在这种情况下, ScaledTranslation很有用。 Unfortunately, seaborn does not allow to use the transform directly and does not give access to the plotted objects. 不幸的是,seaborn不允许直接使用变换,也不允许访问绘制的对象。 Therefore one needs to get the plotted object (in this case the PathCollection) from the axes. 因此,需要从轴获得绘制的对象(在本例中为PathCollection)。 If the plot to be offset is the first plot in the axes ax , we might simply get it via ax.collections[0] . 如果要偏移的图是轴ax的第一个图,我们可以通过ax.collections[0]简单地得到它。 Then we can set the transform to it via .set_transform . 然后我们可以通过.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)

Complete code: 完整代码:

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()

在此输入图像描述

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 ) 要移动线条图,您需要使用其散点( ax.collections[1] )和图中的所有线( ax.lines )执行与上面相同的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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM