Matplotlib/seaborn - 在创建带有循环的子图时设置 yticks/sharey 的问题
Matplotlib/seaborn - problem with set yticks/sharey when creating subplots figure with loop
更新:如果您在这里遇到类似的问题,我在这里找到了适合我的解决方案(请参阅下面的回复);
最好是好的敌人...
我写了一个 for 循环来创建一个两行四列的图形。 x 轴按列共享 (sharex='col'
),按行共享 ya 轴 (sharey='row'
)。它工作得很好......直到我试图在我的循环中使用它来强制第一行的 yaxis 范围:
axes[0, i].set(yticks=range(0,70,10))
现在,当我 运行 代码时,只有子图 axes[0,3]
(即这一行中的最后一个子图)尊重 axes[0, i].set(yticks=range(0,70,10))
行代码。同一行左侧的其他三个子图保留从数据派生的默认 ytick 值(见下图)。
这意味着,尽管 sharey='row'
、axes[0,0]
、axes[0,1]
和 axes[0,2]
共享一个 axes[0,3]
不共享的轴.
如果我设置sharey=False
,那么该行中的所有子图都遵循axes[0, i].set(yticks=range(0,70,10))
代码,但不是根据相同的垂直比例,更不用说sharey=False
也很乱我的第二行子图。
有谁知道为什么 axes[0, i].set(yticks=range(0,70,10))
在循环中似乎只被应用了一次,而不是四次?谢谢。
编辑:我无法提供数据,但基本上我的完整代码如下所示:
fig, axes = plt.subplots(2, 4, figsize=(20, 12), sharex=True, sharey='row')
for i in range(4):
sns.lineplot(ax = axes[0, i], x=x, y=y,
data=data)
sns.despine()
axes[0, i].grid(True, alpha=0.2)
axes[0, i].tick_params(axis='both', which='major', labelsize=13)
axes[0, i].axhline(y=50, color='k', dashes=(2, 1), zorder=0)
axes[0, i].set(yticks=range(0,70,10))
axes[0, 0].set_ylabel('y axis row 0', fontsize=14)
for i in range(4):
sns.lineplot(ax = axes[1, i], x=x1, y=y1,
data=data1)
sns.despine()
axes[1, i].grid(True, alpha=0.2)
axes[1, i].set(xticks=[0, 1, 2, 3, 4])
axes[1, i].axhline(y=0, color='red', dashes=(2, 1), zorder=0)
axes[1, i].tick_params(axis='both', which='major', labelsize=13)
axes[1, 0].set_ylabel('y axis row 1', fontsize=14)
这就是我要说的。看到右上角的子图 axes[0,3]
具有我想要的 yaxis,但同一行的其他子图没有:
这是使用 Seaborn's stock FMRI dataset to show (1) how you can leverage the awesomeness that is Seaborn by using relplot
here and perhaps get rid of your loop; and (2) how you can add an axhline
. Basically, you let relplot
创建你的子图,然后你在每个子图(方面)上有一个简单的小循环来查看图中的数据,然后根据你的条件添加你的线。
在此示例中,region
字段是行标识符,但看起来您会使用行号。
fmri = sns.load_dataset("fmri")
print(fmri)
g = sns.relplot(
data=fmri, x="timepoint", y="signal", row="region",
hue="event", style="event", kind="line",
)
for (row, col, hue_idx), data in g.facet_data():
ax = g.facet_axis(row, col)
myline = 0.2 if data['region'].unique() == "frontal" else -0.1
col = 'red' if data['region'].unique() == "frontal" else 'black'
ax.axhline(myline, c=col, dashes=(2, 1))
plt.show()
编辑:我在此处的解决方案中找到了适合我的解决方案:
通过添加 g = sns.lineplot...
然后在循环内调用 g.axes.set_ylim(0,70)
,我得到了想要的结果。工作代码示例:
fig, axes = plt.subplots(2, 4, figsize=(20, 12), sharex=True, sharey='row')
for i in range(4):
g = sns.lineplot(ax = axes[0, i], x=x, y=y,
data=data)
g.axes.set_ylim(0,70)
axes[0, i].grid(True, alpha=0.2)
axes[0, i].tick_params(axis='both', which='major', labelsize=13)
axes[0, i].axhline(y=50, color='k', dashes=(2, 1), zorder=0)
axes[0, 0].set_ylabel('y0', fontsize=14)
for i in range(4):
sns.lineplot(ax = axes[1, i], x=x1, y=y1,
data=data1)
sns.despine()
axes[1, i].grid(True, alpha=0.2)
axes[1, i].set(xticks=[0, 1, 2, 3, 4])
axes[1, i].axhline(y=0, color='red', dashes=(2, 1), zorder=0)
axes[1, i].tick_params(axis='both', which='major', labelsize=13)
axes[1, 0].set_ylabel('y1', fontsize=14)
更新:如果您在这里遇到类似的问题,我在这里找到了适合我的解决方案(请参阅下面的回复);
最好是好的敌人...
我写了一个 for 循环来创建一个两行四列的图形。 x 轴按列共享 (sharex='col'
),按行共享 ya 轴 (sharey='row'
)。它工作得很好......直到我试图在我的循环中使用它来强制第一行的 yaxis 范围:
axes[0, i].set(yticks=range(0,70,10))
现在,当我 运行 代码时,只有子图 axes[0,3]
(即这一行中的最后一个子图)尊重 axes[0, i].set(yticks=range(0,70,10))
行代码。同一行左侧的其他三个子图保留从数据派生的默认 ytick 值(见下图)。
这意味着,尽管 sharey='row'
、axes[0,0]
、axes[0,1]
和 axes[0,2]
共享一个 axes[0,3]
不共享的轴.
如果我设置sharey=False
,那么该行中的所有子图都遵循axes[0, i].set(yticks=range(0,70,10))
代码,但不是根据相同的垂直比例,更不用说sharey=False
也很乱我的第二行子图。
有谁知道为什么 axes[0, i].set(yticks=range(0,70,10))
在循环中似乎只被应用了一次,而不是四次?谢谢。
编辑:我无法提供数据,但基本上我的完整代码如下所示:
fig, axes = plt.subplots(2, 4, figsize=(20, 12), sharex=True, sharey='row')
for i in range(4):
sns.lineplot(ax = axes[0, i], x=x, y=y,
data=data)
sns.despine()
axes[0, i].grid(True, alpha=0.2)
axes[0, i].tick_params(axis='both', which='major', labelsize=13)
axes[0, i].axhline(y=50, color='k', dashes=(2, 1), zorder=0)
axes[0, i].set(yticks=range(0,70,10))
axes[0, 0].set_ylabel('y axis row 0', fontsize=14)
for i in range(4):
sns.lineplot(ax = axes[1, i], x=x1, y=y1,
data=data1)
sns.despine()
axes[1, i].grid(True, alpha=0.2)
axes[1, i].set(xticks=[0, 1, 2, 3, 4])
axes[1, i].axhline(y=0, color='red', dashes=(2, 1), zorder=0)
axes[1, i].tick_params(axis='both', which='major', labelsize=13)
axes[1, 0].set_ylabel('y axis row 1', fontsize=14)
这就是我要说的。看到右上角的子图 axes[0,3]
具有我想要的 yaxis,但同一行的其他子图没有:
这是使用 Seaborn's stock FMRI dataset to show (1) how you can leverage the awesomeness that is Seaborn by using relplot
here and perhaps get rid of your loop; and (2) how you can add an axhline
. Basically, you let relplot
创建你的子图,然后你在每个子图(方面)上有一个简单的小循环来查看图中的数据,然后根据你的条件添加你的线。
在此示例中,region
字段是行标识符,但看起来您会使用行号。
fmri = sns.load_dataset("fmri")
print(fmri)
g = sns.relplot(
data=fmri, x="timepoint", y="signal", row="region",
hue="event", style="event", kind="line",
)
for (row, col, hue_idx), data in g.facet_data():
ax = g.facet_axis(row, col)
myline = 0.2 if data['region'].unique() == "frontal" else -0.1
col = 'red' if data['region'].unique() == "frontal" else 'black'
ax.axhline(myline, c=col, dashes=(2, 1))
plt.show()
编辑:我在此处的解决方案中找到了适合我的解决方案:
通过添加 g = sns.lineplot...
然后在循环内调用 g.axes.set_ylim(0,70)
,我得到了想要的结果。工作代码示例:
fig, axes = plt.subplots(2, 4, figsize=(20, 12), sharex=True, sharey='row')
for i in range(4):
g = sns.lineplot(ax = axes[0, i], x=x, y=y,
data=data)
g.axes.set_ylim(0,70)
axes[0, i].grid(True, alpha=0.2)
axes[0, i].tick_params(axis='both', which='major', labelsize=13)
axes[0, i].axhline(y=50, color='k', dashes=(2, 1), zorder=0)
axes[0, 0].set_ylabel('y0', fontsize=14)
for i in range(4):
sns.lineplot(ax = axes[1, i], x=x1, y=y1,
data=data1)
sns.despine()
axes[1, i].grid(True, alpha=0.2)
axes[1, i].set(xticks=[0, 1, 2, 3, 4])
axes[1, i].axhline(y=0, color='red', dashes=(2, 1), zorder=0)
axes[1, i].tick_params(axis='both', which='major', labelsize=13)
axes[1, 0].set_ylabel('y1', fontsize=14)