土壤类型或土地利用数据的变量是UNIQ类型,不是连续值,绘制填色图时,不推荐使用等值线填色绘制,使用格点填色图(pcolormash)
注意:UNIQ是离散的,但是colbar的刻度是连续的。自动的设置colorbar刻度基本不会放在对应颜色的中间,需要设置一定的偏移量。
如果需要在colorbar中去除图中没有出现过的颜色,需要对原来的数据进行重新映射!!!
下列给出绘制的主要代码:
函数部分:
import matplotlib.pyplot as plt
import numpy as np
import cartopy.crs as ccrs
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
import cartopy.io.shapereader as shpreader
import rasterio
from matplotlib.colors import ListedColormap
plt.rcParams['font.family'] = 'Times New Roman' # 设置字体为 Times New Roman
plt.rcParams['font.size'] = 24
soil_file = '/China.tif'
#--------------------------------------------------------
def Soil_types(uniq=None):
"""
为地表土壤类型分类提供颜色映射和标签。
参数:
uniq (array-like, 可选): 地表类型的唯一标识符,默认是 [0, 1, 2, ..., 12]。
返回:
cm (ListedColormap): 地表覆盖的颜色映射。
labels (array-like): 每个地表类型的标签。
"""
if uniq is None: # 默认包含所有地表类型
uniq = np.arange(0, 13)
inds = uniq
# 用户提供的颜色列表
colors = [
'#D3D3D3', # 0 unclassified
"#9370DB", # 1 clay(heavy)
"#DA70D6", # 2 silty clay
"#FFB6C1", # 3 clay
"#FFA07A", # 4 silty clay loam
"#B22222", # 5 clay loam
"#FFFACD", # 6 silt
"#FFE4B5", # 7 silt loam
"#90EE90", # 8 sandy clay
"#E1FFFF", # 9 loam
"#00FFFF", # 10 sandy clay loam
"#87CEFA", # 11 sandy loam
"#6495ED", # 12 loamy sand
]
# 提取指定类型的颜色
cm = ListedColormap(np.array(colors)[inds])
# 地表类型标签
labels = [
'unclassified', # 0
"clay(heavy)", # 1
"silty clay", # 2
"clay", # 3
"silty clay loam", # 4
"clay loam", # 5
"silt", # 6
"silt loam", # 7
"sandy clay", # 8
"loam", # 9
"sandy clay loam", # 10
"sandy loam", # 11
"loamy sand", # 12
]
return cm, np.array(labels)[inds]
def ld1(data):
"""
处理地表覆盖分类数据并返回绘图相关的属性。
参数:
data: 地表覆盖数据,可以是 NumPy 数组或其他支持转换为 NumPy 数组的格式。
返回:
- ticks: 刻度位置,用于设置图例或色带。
- labels: 地表覆盖类型的标签列表。
- cm: 颜色映射 (ListedColormap)。
- n_max: 地表覆盖类型的数量。
"""
cm, labels = Soil_types()
n_max = len(labels)-1 # 最大值是 n_max, 这里减去 1 使得最后的 ticks 是 0 到 n_max 范围
ticks = np.linspace(0, n_max, n_max + 2)
#土壤类型的数值是是0~12,共13个,需要13个对应的颜色。
#colorbar的刻度类似于数轴,将数轴分为13等分需要砍14刀(14到里有两刀在数轴的两端,所以比平时理解的多了两刀)
#砍了两刀后,产生了14个数值,但是这14个数值位置是在颜色的分界线上,这里需要的是在每个颜色的中间,
#所以,需要将相邻的数值求平均后,就得到了每个颜色中间的数值。
new_ticks = (ticks[:-1] + ticks[1:]) / 2
return new_ticks, labels, cm, n_max
绘图部分
fig = plt.figure(figsize=(12, 12),dpi=300)
ax = fig.add_axes([0, 0, 1, 1], projection=ccrs.PlateCarree())
ax.set_extent([70, 140, 0, 55])
new_ticks, labels, cm ,n_max = ld1(data)
im = ax.pcolormesh(lon, lat, data, vmin=0, vmax=12 ,
cmap=cm, alpha=0.8, transform=ccrs.PlateCarree())
cbar = plt.colorbar(im, ax=ax ,orientation='horizontal', pad=0.05)
cbar.set_ticks(new_ticks)
cbar.ax.set_xticklabels(labels,fontsize=15)
for label in cbar.ax.get_xticklabels():
label.set_rotation(30)
shapefile_path = '省界.shp'
reader = shpreader.Reader(shapefile_path)
ax.add_geometries(reader.geometries(), crs=ccrs.PlateCarree(), edgecolor='k',
facecolor='none', linewidth=1.2)