我需要更改颜色条刻度的位置,并且需要帮助。到目前为止,我已经尝试了一些方法,但是没有一种方法能够令人满意。
我有以下类型的数据框:
import pandas as pd
import random
country_iso = ['RU', 'FR', 'HU', 'AT', 'US', 'ES', 'DE', 'CH', 'LV', 'LU']
my_randoms=[random.uniform(0.0, 0.3) for _ in range (len(country_iso))]
df = pd.DataFrame({'iso':country_iso, 'values':my_randoms})
df.loc[df.iso.str.contains('US')]= ['US', 0]
df['binned']=pd.cut(df['values'], bins=[-0.01, 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3], labels=[0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3])
df.binned = pd.to_numeric(df.binned, errors='coerce')
df = df[['iso', 'binned']]
如您所见,这是一个数据集,其中等值国家值作为一列,另一些作为第二列,其装箱值在0到0.3之间。美国的值为0,我希望它具有不同的颜色。然后,我使用natural earth中的shapefile创建底图。
from matplotlib import pyplot as plt, colors as clr, cm
from mpl_toolkits.basemap import Basemap
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
from matplotlib.ticker import FuncFormatter
import numpy as np
shapefile_path = #path to your shapefile
fig, ax = plt.subplots(figsize=(10,20))
m = Basemap(resolution='c', # c, l, i, h, f or None
projection='mill',
llcrnrlat=-62, urcrnrlat=85,
llcrnrlon=-180, urcrnrlon=180)
m.readshapefile(shapefile_path+r'\ne_110m_admin_0_countries', 'areas')
df_poly = pd.DataFrame({
'shapes': [Polygon(np.array(shape), True) for shape in m.areas],
'iso': [gs['ISO_A2'] for gs in m.areas_info]
})
df_poly = df_poly.merge(df, on='iso', how='inner', indicator=True)
cmap = clr.LinearSegmentedColormap.from_list('custom blue', ['#d0dfef', '#24466b'], N=7)
cmap._init()
cmap._lut[0,: ] = np.array([200,5,5,200])/255
pc = PatchCollection(df_poly[df_poly[df.columns[1]].notnull()].shapes, zorder=2)
norm = clr.Normalize()
pc.set_facecolor(cmap(norm(df_poly[df_poly[df.columns[1]].notnull()][df.columns[1]].values)))
ax.add_collection(pc)
mapper = cm.ScalarMappable(norm=norm, cmap=cmap)
mapper.set_array(df_poly[df_poly[df.columns[1]].notnull()][df.columns[1]])
clb = plt.colorbar(mapper, shrink=0.19)
我创建了一个蓝色的cmap,但是将第一个颜色更改为红色。这是因为我希望值为0的国家/地区具有不同的颜色。一切都很棒,但是如果您查看颜色栏,刻度线就会偏离中心。
有人知道如何更正我的代码吗?非常感谢!
答案 0 :(得分:2)
将示例简化为基本要素,可以通过扩展传递给映射器的范围来实现所需的目标。我想将颜色图扩展到负值是否有意义取决于具体的用例。无论如何,这是一个不包含Basemap
和shapefiles
的完整示例,这对于此问题不是必需的。
from matplotlib import pyplot as plt, colors as clr, cm
import numpy as np
fig= plt.figure()
ax = plt.subplot2grid((1,20),(0,0), colspan=19)
cax = plt.subplot2grid((1,20),(0,19))
upper = 0.3
lower = 0.0
N = 7
cmap = clr.LinearSegmentedColormap.from_list(
'custom blue', ['#d0dfef', '#24466b'], N=N
)
cmap._init()
cmap._lut[0,: ] = np.array([200,5,5,200])/255.0
norm = clr.Normalize()
mapper = cm.ScalarMappable(norm=norm, cmap=cmap)
deltac = (upper-lower)/(2*(N-1))
mapper.set_array(np.linspace(lower-deltac,upper+deltac,10)) #<-- the 10 here is pretty arbitrary
clb = fig.colorbar(mapper, shrink=0.19, cax=cax)
plt.show()
我在颜色栏的垂直扩展上遇到了一些问题,这就是为什么我选择使用cax
关键字的原因。另请注意,在Python 2中,整数除法存在一个小问题。因此,我将除法从/255
更改为/255.0
。最终结果如下所示:
希望这会有所帮助。
编辑:
显然,对norm()
的调用会更改Normalize
对象的状态。通过向Normalize
构造函数提供新的ScalarMappable
对象,代码按预期开始工作。我仍然困惑为什么会这样。无论如何,在完整的代码下方生成了图和颜色条(请注意,我更改了图形大小和颜色条缩放比例):
from matplotlib import pyplot as plt, colors as clr, cm
from mpl_toolkits.basemap import Basemap
from matplotlib.patches import Polygon
import pandas as pd
import random
country_iso = ['RU', 'FR', 'HU', 'AT', 'US', 'ES', 'DE', 'CH', 'LV', 'LU']
my_randoms=[random.uniform(0.0, 0.3) for _ in range (len(country_iso))]
df = pd.DataFrame({'iso':country_iso, 'values':my_randoms})
df.loc[df.iso.str.contains('US')]= ['US', 0]
df['binned']=pd.cut(df['values'], bins=[-0.01, 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3], labels=[0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3])
df.binned = pd.to_numeric(df.binned, errors='coerce')
df = df[['iso', 'binned']]
import numpy as np
from matplotlib.collections import PatchCollection
from matplotlib.ticker import FuncFormatter
shapefile_path = 'shapefiles/'
fig, ax = plt.subplots()#figsize=(10,20))
upper = 0.3
lower = 0.0
N = 7
deltac = (upper-lower)/(2*(N-1))
m = Basemap(resolution='c', # c, l, i, h, f or None
projection='mill',
llcrnrlat=-62, urcrnrlat=85,
llcrnrlon=-180, urcrnrlon=180,
ax = ax,
)
m.readshapefile(shapefile_path+r'ne_110m_admin_0_countries', 'areas')
df_poly = pd.DataFrame({
'shapes': [Polygon(np.array(shape), True) for shape in m.areas],
'iso': [gs['ISO_A2'] for gs in m.areas_info]
})
df_poly = df_poly.merge(df, on='iso', how='inner', indicator=True)
cmap = clr.LinearSegmentedColormap.from_list('custom blue', ['#d0dfef', '#24466b'], N=N)
cmap._init()
cmap._lut[0,: ] = np.array([200,5,5,200])/255.0
pc = PatchCollection(df_poly[df_poly[df.columns[1]].notnull()].shapes, zorder=2)
norm = clr.Normalize()
pc.set_facecolor(cmap(norm(df_poly[df_poly[df.columns[1]].notnull()][df.columns[1]].values)))
ax.add_collection(pc)
mapper = cm.ScalarMappable(norm=clr.Normalize(), cmap=cmap)
mapper.set_array([lower-deltac,upper+deltac])
clb = plt.colorbar(mapper, shrink=0.55)
plt.show()
结果图如下: