问题
I am speaking to those who know Cartopy well ... because I use Cartopy to produce a map, but I do not know very well how it works.
First, I created a map of Europe (in the broadest sense, from the Atlantic to the Urals), as shown in the attached figure.
Then, I have a separate file, say dft0
, indicating for each European country the time of appearance (Time0
) of a certain phenomenon, counted in number of days with respect to an arbitrary date D
and sorted from min
to max
; as an example of the first rows:
Country Time0
20 Italy -16.063702
10 Denmark -2.798684
39 Sweden -2.711578
15 Germany 3.259436
So, the so-called phenomenon appeared first in Italy, 16.1 days
before my date D
, then in Denmark, 2.8 days
before D
, then in Sweden, 2.7 days
before D
, then in Germany, 3.3 days
after D
, etc., going to Belarus, where it appeared 52.1 days
after D
.
52.1
.
There are 44 such values (from negative to positive) in file dft0
, from -16.1
to 52.1
.
My question is: knowing that I did a suitable program to draw the map of Europe, what kind of code should I have to add to the program in order to color the countries according to the variable Time0
, for example from red
(for Italy) to violet
(for Belarus), following the colors of the visible spectrum, in which red = 800 nm
and violet = 400 nm
?
More precisely, if Time0 = x
, I would like to color the corresponding country with the color corresponding to (approximately) y = -5.9 x + 705.6 nm
.
To be more understandable, I inserted a plot showing how to calculate the color y
(in nm
); it's a basic linear interpolation.
I really don't know if it can be done, as it seems to be complicated (may be unnecessarily complicated). So, I am open to any other idea. The aim is to differentiate the 44
countries I have in this file dft0
, with an ordered palette of colors, showing a regular decrease (or a regular growth...)
Thank you for your concern.
Added: the Cartopy program I used:
import matplotlib.pyplot as plt
import cartopy
import cartopy.io.shapereader as shpreader
plt.figure(figsize=(4, 4))
central_lon, central_lat = 0, 45
extent = [-10, 45, 35, 70]
ax = plt.axes(projection=cartopy.crs.Orthographic(central_lon, central_lat))
ax.set_extent(extent)
ax.gridlines()
ax.add_feature(cartopy.feature.BORDERS, linestyle=':', alpha=1)
ax.add_feature(cartopy.feature.OCEAN,facecolor=("lightblue"))
ax.add_feature(cartopy.feature.LAND)
ax.coastlines(resolution='10m')
plt.show()
回答1:
This solution is based on your posted code sample and draws heavily on this answer
import matplotlib.pyplot as plt
import matplotlib
import cartopy
from cartopy.io import shapereader
import cartopy.crs as ccrs
import geopandas
import numpy as np
# get natural earth data (http://www.naturalearthdata.com/)
# get country borders
resolution = '10m'
category = 'cultural'
name = 'admin_0_countries'
shpfilename = shapereader.natural_earth(resolution, category, name)
# read the shapefile using geopandas
df = geopandas.read_file(shpfilename)
# Set up the canvas
fig = plt.figure(figsize=(8, 8))
central_lon, central_lat = 0, 45
extent = [-10, 45, 35, 70]
ax = plt.axes(projection=cartopy.crs.Orthographic(central_lon, central_lat))
ax.set_extent(extent)
ax.gridlines()
# Add natural earth features and borders
ax.add_feature(cartopy.feature.BORDERS, linestyle=':', alpha=1)
ax.add_feature(cartopy.feature.OCEAN, facecolor=("lightblue"))
ax.add_feature(cartopy.feature.LAND)
ax.coastlines(resolution='10m')
# Insert your lists of countries and lag times here
countries = ['Germany', 'France', 'Italy', 'Spain', 'Ukraine']
lags = [-20,-5, 15, 0, 2]
# Normalise the lag times to between 0 and 1 to extract the colour
lags_norm = (lags-np.nanmin(lags))/(np.nanmax(lags) - np.nanmin(lags))
# Choose your colourmap here
cmap = matplotlib.cm.get_cmap('viridis')
for country, lag_norm in zip(countries, lags_norm):
# read the borders of the country in this loop
poly = df.loc[df['ADMIN'] == country]['geometry'].values[0]
# get the color for this country
rgba = cmap(lag_norm)
# plot the country on a map
ax.add_geometries(poly, crs=ccrs.PlateCarree(), facecolor=rgba, edgecolor='none', zorder=1)
# Add a scatter plot of the original data so the colorbar has the correct numbers. Hacky but it works
dummy_scat = ax.scatter(lags, lags, c=lags, cmap=cmap, zorder=0)
fig.colorbar(mappable=dummy_scat, label='Time lag of phenomenon', orientation='horizontal', shrink=0.8)
result:
Map of Europe with France, Germany and Italy coloured
As for the colouring by the visible spectrum, I would strongly dissuade you from dong this unless you have a very good reason to do so. Instead I have used one of matplotlib's inbuilt perceptually uniform colourmaps. There are many other colormaps you can use if viridis doesn't suit your needs. These perceptually uniform colormaps are preferable as they do not distort your data. For more information check out this page or this more in depth discussion, or search for information on perceptually uniform colourmaps. Viewers of your work (especially those with colour vision deficiency) will thank you.
来源:https://stackoverflow.com/questions/61460814/color-cartopy-map-countries-according-to-given-values