为不同范围的多个 matplotlib 子图设置 'global' 颜色条范围
Set 'global' colorbar range for multiple matplotlib subplots of different ranges
我想在 python 中使用 matplotlib.pyplot 在子图中绘制数据。每个子图将包含不同范围的数据。我想使用 pyplot.scatter 绘制它们,并为整个图使用一个单一的颜色条。因此,颜色条应包含每个子图中值的整个范围。但是,当我使用循环绘制子图并在循环外调用颜色条时,它仅使用最后一个子图的值范围。许多可用的示例都涉及调整颜色条位置的大小,因此这个答案(如何为多个子图制作一个通用颜色条)并不明显。
我有以下独立的示例代码。这里渲染了两个子图,一个应该用俄罗斯典型的寒冷温度着色,另一个用巴西的热带温度着色。然而,最终结果显示的颜色条仅在巴西热带温度范围内变化,使得俄罗斯子图错误:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
core_list = ['Russia', 'Brazil']
core_depth = [0, 2, 4, 6, 8, 10]
lo = [-33, 28]
hi = [10, 38]
df = pd.DataFrame([], columns = ['Location', 'Depth', '%TOC', 'Temperature'])
#Fill df
for ii, name in enumerate(core_list):
for jj in core_depth:
df.loc[len(df.index)] = [name, jj, (np.random.randint(1, 20))/10, np.random.randint(lo[ii], hi[ii])]
#Russia data have much colder temperatures than Brazil data due to hi and lo
#Plot data from each location using scatter plots
fig, axs = plt.subplots(nrows = 1, ncols = 2, sharey = True)
for nn, name in enumerate(core_list):
core_mask = df['Location'] == name
data = df.loc[core_mask]
plt.sca(axs[nn])
plt.scatter(data['Depth'], data['%TOC'], c = data['Temperature'], s = 50, edgecolors = 'k')
axs[nn].set_xlabel('%TOC')
plt.text(1.25*min(data['%TOC']), 1.75, name)
if nn == 0:
axs[nn].set_ylabel('Depth')
cbar = plt.colorbar()
cbar.ax.set_ylabel('Temperature, degrees C')
#How did Russia get so warm?!? Temperatures and ranges of colorbar are set to last called location.
#How do I make one colorbar encompass global temperature range of both data sets?
此代码的输出显示巴西和俄罗斯的温度落在相同的颜色范围内:
我们直觉地知道,从数据来看,这是错误的。那么,我们如何告诉 pyplot 正确绘制它呢?
答案很简单,使用 pyplot.scatter
的 vmax 和 vmin 控件。这些必须使用通用范围的数据设置,而不仅仅是在循环的任何单个迭代中关注的数据。因此,要更改上面的代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
core_list = ['Russia', 'Brazil']
core_depth = [0, 2, 4, 6, 8, 10]
lo = [-33, 28]
hi = [10, 38]
df = pd.DataFrame([], columns = ['Location', 'Depth', '%TOC', 'Temperature'])
#Fill df
for ii, name in enumerate(core_list):
for jj in core_depth:
df.loc[len(df.index)] = [
name,
jj,
(np.random.randint(1, 20))/10,
np.random.randint(lo[ii], hi[ii])
]
#Russia data have much colder temperatures than Brazil data due to hi and lo
#Plot data from each location using scatter plots
fig, axs = plt.subplots(nrows = 1, ncols = 2, sharey = True)
for nn, name in enumerate(core_list):
core_mask = df['Location'] == name
data = df.loc[core_mask]
plt.sca(axs[nn])
plt.scatter(
data['Depth'],
data['%TOC'],
c=data['Temperature'],
s=50,
edgecolors='k',
vmax=max(df['Temperature']),
vmin=min(df['Temperature'])
)
axs[nn].set_xlabel('%TOC')
plt.text(1.25*min(data['%TOC']), 1.75, name)
if nn == 0:
axs[nn].set_ylabel('Depth')
cbar = plt.colorbar()
cbar.ax.set_ylabel('Temperature, degrees C')
现在,输出显示了俄罗斯和巴西之间的温差,这是粗略浏览数据后所预料到的。修复此问题的更改发生在 for 循环中,但是它引用所有数据来查找最大值和最小值:
plt.scatter(data['Depth'], data['%TOC'], c = data['Temperature'], s = 50, edgecolors = 'k',
vmax = max(df['Temperature']), vmin = min(df['Temperature']) )
我想在 python 中使用 matplotlib.pyplot 在子图中绘制数据。每个子图将包含不同范围的数据。我想使用 pyplot.scatter 绘制它们,并为整个图使用一个单一的颜色条。因此,颜色条应包含每个子图中值的整个范围。但是,当我使用循环绘制子图并在循环外调用颜色条时,它仅使用最后一个子图的值范围。许多可用的示例都涉及调整颜色条位置的大小,因此这个答案(如何为多个子图制作一个通用颜色条)并不明显。
我有以下独立的示例代码。这里渲染了两个子图,一个应该用俄罗斯典型的寒冷温度着色,另一个用巴西的热带温度着色。然而,最终结果显示的颜色条仅在巴西热带温度范围内变化,使得俄罗斯子图错误:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
core_list = ['Russia', 'Brazil']
core_depth = [0, 2, 4, 6, 8, 10]
lo = [-33, 28]
hi = [10, 38]
df = pd.DataFrame([], columns = ['Location', 'Depth', '%TOC', 'Temperature'])
#Fill df
for ii, name in enumerate(core_list):
for jj in core_depth:
df.loc[len(df.index)] = [name, jj, (np.random.randint(1, 20))/10, np.random.randint(lo[ii], hi[ii])]
#Russia data have much colder temperatures than Brazil data due to hi and lo
#Plot data from each location using scatter plots
fig, axs = plt.subplots(nrows = 1, ncols = 2, sharey = True)
for nn, name in enumerate(core_list):
core_mask = df['Location'] == name
data = df.loc[core_mask]
plt.sca(axs[nn])
plt.scatter(data['Depth'], data['%TOC'], c = data['Temperature'], s = 50, edgecolors = 'k')
axs[nn].set_xlabel('%TOC')
plt.text(1.25*min(data['%TOC']), 1.75, name)
if nn == 0:
axs[nn].set_ylabel('Depth')
cbar = plt.colorbar()
cbar.ax.set_ylabel('Temperature, degrees C')
#How did Russia get so warm?!? Temperatures and ranges of colorbar are set to last called location.
#How do I make one colorbar encompass global temperature range of both data sets?
此代码的输出显示巴西和俄罗斯的温度落在相同的颜色范围内:
我们直觉地知道,从数据来看,这是错误的。那么,我们如何告诉 pyplot 正确绘制它呢?
答案很简单,使用 pyplot.scatter
的 vmax 和 vmin 控件。这些必须使用通用范围的数据设置,而不仅仅是在循环的任何单个迭代中关注的数据。因此,要更改上面的代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
core_list = ['Russia', 'Brazil']
core_depth = [0, 2, 4, 6, 8, 10]
lo = [-33, 28]
hi = [10, 38]
df = pd.DataFrame([], columns = ['Location', 'Depth', '%TOC', 'Temperature'])
#Fill df
for ii, name in enumerate(core_list):
for jj in core_depth:
df.loc[len(df.index)] = [
name,
jj,
(np.random.randint(1, 20))/10,
np.random.randint(lo[ii], hi[ii])
]
#Russia data have much colder temperatures than Brazil data due to hi and lo
#Plot data from each location using scatter plots
fig, axs = plt.subplots(nrows = 1, ncols = 2, sharey = True)
for nn, name in enumerate(core_list):
core_mask = df['Location'] == name
data = df.loc[core_mask]
plt.sca(axs[nn])
plt.scatter(
data['Depth'],
data['%TOC'],
c=data['Temperature'],
s=50,
edgecolors='k',
vmax=max(df['Temperature']),
vmin=min(df['Temperature'])
)
axs[nn].set_xlabel('%TOC')
plt.text(1.25*min(data['%TOC']), 1.75, name)
if nn == 0:
axs[nn].set_ylabel('Depth')
cbar = plt.colorbar()
cbar.ax.set_ylabel('Temperature, degrees C')
现在,输出显示了俄罗斯和巴西之间的温差,这是粗略浏览数据后所预料到的。修复此问题的更改发生在 for 循环中,但是它引用所有数据来查找最大值和最小值:
plt.scatter(data['Depth'], data['%TOC'], c = data['Temperature'], s = 50, edgecolors = 'k',
vmax = max(df['Temperature']), vmin = min(df['Temperature']) )