python - 我如何根据 12 个数组(12 个月)制作颜色图?
问题描述
我的目标是创建一个基于月份的彩色地图。我有两个月度数据数据集(相同长度等)。但是我想绘制两个数据集的散点图,但是颜色图要根据月份着色。希望这在我浏览示例时更有意义:
这些是我作为散点图相互绘制的两个数据集:
data1 = np.random.rand(360)
data2 = np.random.rand(360)
然后我使用这个函数 (split_months) 将 data1 和 data2 转换为大小为 12、30 的二维数组。这就像按月重新组合,其中 12 代表所有月份,而 30 是该特定月份的所有年份:
def split_months(monthly_data):
month_split = []
for month in range(12):
month_split.append(monthly_data[month::12])
month_split = np.array(month_split)
return month_split
split_data1 = split_months(data1)
split_data2 = split_months(data2)
print(split_data1.shape, split_data2.shape)
(12, 30) (12, 30)
然后,我通过基本上将第一个月和所有年份,然后是第二个月和所有年份,将拆分月份数据重塑为一维数组。因此制作一个一维数组,但按月重新排序,因此按年数重新排序(如下面的示例所示):
split_months_reshape_data1= split_data1.reshape(12*30) ## reshaping so organized by month now (jan - dec for all years)
split_months_reshape_data2 = split_data2.reshape(12*30)
print(split_data1[0])
print(split_months_reshape_data1[:30])
[0.70049451 0.24326443 0.29633189 0.35540148 0.68205274 0.15130453
0.34046832 0.54975106 0.4502673 0.39086571 0.5610824 0.88443547
0.85777702 0.39887896 0.82240821 0.31162978 0.23496537 0.68776803
0.84677736 0.04060598 0.7735167 0.23317739 0.49447141 0.53932027
0.62494628 0.19676697 0.41435389 0.22843223 0.22817976 0.09133836]
[0.70049451 0.24326443 0.29633189 0.35540148 0.68205274 0.15130453
0.34046832 0.54975106 0.4502673 0.39086571 0.5610824 0.88443547
0.85777702 0.39887896 0.82240821 0.31162978 0.23496537 0.68776803
0.84677736 0.04060598 0.7735167 0.23317739 0.49447141 0.53932027
0.62494628 0.19676697 0.41435389 0.22843223 0.22817976 0.09133836]
## data arrays are the same, split_months is showing all of the numbers for the first month, while split_months_reshape_data1 is showing the first 30 values which is the same as the `split_months[0]`
现在的问题是,有没有办法使用 split_months 中的 12 个数组中的每一个来创建颜色图(1 月 - 12 月),但在每个数组中使用这些特定值?例如,对于一月,使用 from 的值为split_months[0]
颜色图制作一种颜色。然后对于二月,使用来自的值为split_months[1]
颜色图制作另一种颜色
这是我想要的想法,但颜色条不正确:
plt.scatter(split_months_reshape_data1,split_months_reshape_data2, c = split_data1)
plt.colorbar()
plt.show()
plt.show()
如果我的问题需要澄清,请告诉我,它有点具体,但主要目标是获得基于重塑数据数组 (split_data1
和split_data2
) 的颜色图。
解决方案
从颜色图中选择颜色非常简单,如matplotlib 颜色图教程中所示。有两种类型的颜色图对象(LinearSegmentedColormap 和 ListedColormap),它们没有完全相同的颜色选择方法。以下是如何使用pyplot 界面从 viridis 颜色图 (ListedColormap) 中选择颜色:
# Select colormap with a certain number of colors
cmap = plt.cm.get_cmap('viridis', 12)
# Generate list of colors in these 3 equivalent ways for a ListeColormap
colors = cmap.colors # this method is not applicable to LinearSegmentedColormaps
colors = cmap(range(12))
colors = cmap(np.linspace(0, 1, 12))
创建颜色条是比较棘手的部分。您正在绘制的数据集包含 3 个变量:
- 月份(分类):绘制为色调
- data1(数字):绘制为 x 变量
- data2(数字):绘制为 y 变量
正如您在示例中看到的,传递给的变量c
(即split_data1
x 变量)映射到使用 创建的颜色栏plt.colorbar()
。虽然可以传递与月份对应的值c
来创建颜色条(参见下图所示的替代解决方案),但我发现如果预先选择月份的颜色然后将其传递给color
. 然后可以从绘图中单独创建颜色条,如自定义颜色条教程的第二个示例所示。
这是一个示例,其中通过使用几个 numpy 函数简化了数据重塑部分,并使用zip创建了散点图以循环遍历子数组以及相关的月份和颜色。月份的名称是使用datetime 模块生成的,以节省一些输入。
from datetime import datetime as dt
import numpy as np # v 1.19.2
import matplotlib.pyplot as plt # v 3.3.4
# Create sample dataset
rng = np.random.default_rng(seed=1) # random number generator
data1 = rng.random(360)
data2 = rng.random(360)
# Reshape data
split_data1 = np.stack(np.split(data1, 30)).transpose()
split_data2 = np.stack(np.split(data2, 30)).transpose()
# Generate lists of months and colors
months = [dt.strptime(str(m), '%m').strftime('%B') for m in range(1, 13)]
cmap = plt.cm.get_cmap('viridis') # no need to preselect number of colors in this case
colors = cmap(np.linspace(0, 1, len(months)))
# Draw scatter plot by looping over zipped sub-arrays, colors and months
for x, y, c, month in zip(split_data1, split_data2, colors, months):
plt.scatter(x, y, color=c, label=month)
# Add colorbar
bounds = np.arange(len(months)+1)
norm = plt.matplotlib.colors.BoundaryNorm(bounds, cmap.N)
cbar = plt.colorbar(plt.cm.ScalarMappable(norm=norm, cmap=cmap), ticks=bounds+0.5)
cbar.set_ticklabels(months)
# Optional extra formatting
cbar.ax.tick_params(length=0, pad=7)
cbar.ax.invert_yaxis()
plt.show()
为了完整起见,这是一个替代解决方案,它使用c
参数 in plt.scatter
(而不是color
)直接从图中生成颜色条:
# Prepare data...
# months and cmap are the same as before
months = [dt.strptime(str(m), '%m').strftime('%B') for m in range(1, 13)]
cmap = plt.cm.get_cmap('viridis')
# Create objects needed to map the months to colors and create a colorbar
bounds = np.arange(13)
norm = plt.matplotlib.colors.BoundaryNorm(bounds, cmap.N)
# Draw scatter plot, notice how there is no need for colors
for x, y, month, bound in zip(split_data1, split_data2, months, bounds):
plt.scatter(x, y, c=np.repeat(bound, len(x)), norm=norm, cmap=cmap, label=month)
cbar = plt.colorbar()
# Format colorbar
cbar.set_ticklabels(months)
cbar.set_ticks(bounds+0.5)
cbar.ax.tick_params(length=0, pad=7)
cbar.ax.invert_yaxis()
推荐阅读
- c - 当涉及到 C 中的 #ifdef name 或 #if defined(name) 时,#define name 和 #define name(arguments) 有什么区别?
- python - 如何在我的 Flask 应用中实现 ReactJS 应用?
- python - 如何反转列表中元组的顺序
- java - SharedPreferences 不适用于 setTextSize
- c++ - 如何获取命令 ID 的键盘加速器?
- angular - 如何将 patchValue 数字与角度形式的字符串连接起来?
- php - Facebook\WebDriver\Exception\WebDriverCurlException:为 http POST 到 /session/...... 抛出 Curl 错误,参数:{"type":"browser"}
- wpf - Powershell上Xaml网格上的重叠按钮与onclick按钮
- javascript - DIVI 中的 Javascript:mouseenter 不起作用
- javascript - Workbox 运行时缓存不适用于带有查询参数的 url?