我试图在一个图中绘制多个图,并发现了一个错误,其中
axS[i] = sns.boxplot(plot)
导致 Seaborn 选择最后一个子图,就好像它忘记了 i
的值一样。注意 print 语句和指向子图的指针的位置——它们应该匹配,但是 sns.boxplot
线把它们弄乱了。
df = pd.read_csv(fold+file,index_col=1)
print(df.columns)
types = ['all cells','1 endothelial','2 immune','3 tumor','4 active fibroblast','5 stromal']
fig,axS = plt.subplots(6,1,sharex=True,figsize=(20,8))
for i,ty in enumerate(types):
if i == 0:
plot = df.loc[:,bioms]
else:
key = df.loc[:,'SVM_primary'] == ty
sdf = df.loc[key,bioms]
plot = sdf
print('\n',i,ty)
print(axS[i]) #First important print statement
axS[i] = sns.boxplot(plot)
print(axS[i]) #Second: should be identical, but it's not!
axS[i].title.set_text(ty)
plt.xticks(rotation = 90)
fig.tight_layout()
plt.show()
输出为:
0 all cells
AxesSubplot(0.125,0.77;0.775x0.11)
AxesSubplot(0.125,0.11;0.775x0.11)
1 1 endothelial
AxesSubplot(0.125,0.638;0.775x0.11) #
AxesSubplot(0.125,0.11;0.775x0.11) # this pointer should be the same as the one above it
2 2 immune
AxesSubplot(0.125,0.506;0.775x0.11)
AxesSubplot(0.125,0.11;0.775x0.11)
3 3 tumor
AxesSubplot(0.125,0.374;0.775x0.11)
AxesSubplot(0.125,0.11;0.775x0.11)
4 4 active fibroblast
AxesSubplot(0.125,0.242;0.775x0.11)
AxesSubplot(0.125,0.11;0.775x0.11)
5 5 stromal
AxesSubplot(0.125,0.11;0.775x0.11)
AxesSubplot(0.125,0.11;0.775x0.11)
脚本正确识别了
i
,但在两个print(axS[i])
语句中,第一个正确识别了指向新子图的唯一指针,然后在调用SNS图后,它认为这是最后一个子图(就好像i
变成了5)每次调用 sns.boxplot
时)。我希望我错过了一些东西。
这不是seaborn的错误,这是对seaborn工作原理的误解(以及对python的一般误解)。
从普遍的误解开始。假设你有一个清单。
x = [1, 2, 3]
如果您为其建立索引并更改值,则会更新列表。
x[1] = 5
print(x) # [1, 5, 3]
因此,当您调用
sns.boxplot
时,它会返回一个轴对象,您可以用它来覆盖 axS[i]
。
当您调用
sns.boxplot
时,您并没有告诉seaborn要使用哪个轴,因此默认情况下它将使用最新图形的最后一个轴。
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
x = np.arange(0, 10, 0.01)
y1 = x**2
y2 = np.sin(x)
fig, axes = plt.subplots(1, 2)
a = sns.lineplot(x=x, y=y1)
看到它如何使用图中的最后一个轴了吗?我将返回保存到
a
,我可以检查它是否等于最后一个轴。
print(a == axes[-1]) # True
要在正确的轴上绘图,您必须将其作为关键字参数传递给seaborn。
fig, axes = plt.subplots(1, 2)
a = sns.lineplot(x=x, y=y1, ax=axes[0])
b = sns.lineplot(x=x, y=y2, ax=axes[1])
作为支票:
print(a == axes[0]) # True
print(b == axes[1]) # True
因此,总之,将轴传递给箱线图调用,并且不要用返回值覆盖轴列表(尽管一旦绘制到正确的轴,它就不会执行任何操作)。
sns.boxplot(plot, ax=axS[i])