How to generate a map of European countries coloured according to a vector of positive and negative values?

38 views (last 30 days)
Hello all,
I am trying to get a map of the European countries (cou_nam) in which the color of each country is assigned according to a vector including 0, positive and negative values (data).
The approach I follow is based on both the Mapping Toolbox as well as the borders file exchange submission.
% country names
cou_nam = {'Belgium', 'Bulgaria', 'Czech Republic', 'Denmark', 'Germany','Estonia','Ireland',...
'Greece','Spain','France','Croatia','Italy', 'Cyprus','Latvia', 'Lithuania', 'Luxembourg',...
'Hungary', 'Malta', 'Netherlands','Austria', 'Poland', 'Portugal','Romania','Slovenia', 'Slovakia',...
'Finland', 'Sweden'};
numRegions = length(cou_nam);
cmap = colormap;
% Random vector of values (one for each country)
data = randi([-5,5],numRegions,1);
% Map
figure('Color','w')
xh = worldmap('Europe');
setm(xh,'MapProjection','miller')
tightmap
geoshow ('landareas.shp', 'FaceColor', 'white');
for i = 1:1:numRegions
bordersm(cou_nam{i},'facecolor',cmap(data(i),:)) % => problem with negative values
end
colorbar
The issue with this code is that the variable data stores both negative and positive values, so when called in the for loop gets back an error since only positive integers are accepted.
Also, if I insert only positive values, i.e.
data = randi([1,5],numRegions,1);
it seems that the colorbar doesn't conform with the range of the values in data.
I have seen that there are similar questions (here and here) in the Community, yet I have not managed to get a solution.
Thanks!

Accepted Answer

DGM
DGM on 26 Apr 2022
Edited: DGM on 26 Apr 2022
This should work. Note that the placeholder data isn't even integer-valued.
% country names
cou_nam = {'Belgium', 'Bulgaria', 'Czech Republic', 'Denmark', 'Germany','Estonia','Ireland',...
'Greece','Spain','France','Croatia','Italy', 'Cyprus','Latvia', 'Lithuania', 'Luxembourg',...
'Hungary', 'Malta', 'Netherlands','Austria', 'Poland', 'Portugal','Romania','Slovenia', 'Slovakia',...
'Finland', 'Sweden'};
numRegions = length(cou_nam);
cmap = jet(256); % specify the colormap
% Random vector of values (one for each country)
datarange = [-5 5]; % get the actual range of the data
data = range(datarange)*rand(numRegions,1) + min(datarange); % i'm assuming this is a placeholder
coloridx = round(rescale(data,1,size(cmap,1))); % rescale the data to use as an index into cmap
% Map
figure('Color','w')
xh = worldmap('Europe');
setm(xh,'MapProjection','miller')
tightmap
geoshow ('landareas.shp', 'FaceColor', 'white');
for i = 1:1:numRegions
bordersm(cou_nam{i},'facecolor',cmap(coloridx(i),:))
end
colorbar
colormap(cmap) % specify the colormap
caxis(datarange) % set caxis to match datarange
  3 Comments
DGM
DGM on 26 Apr 2022
If your data is relatively centered about 0, then you can do that by just using a colormap that's gray in the middle.
% country names
cou_nam = {'Belgium', 'Bulgaria', 'Czech Republic', 'Denmark', 'Germany','Estonia','Ireland',...
'Greece','Spain','France','Croatia','Italy', 'Cyprus','Latvia', 'Lithuania', 'Luxembourg',...
'Hungary', 'Malta', 'Netherlands','Austria', 'Poland', 'Portugal','Romania','Slovenia', 'Slovakia',...
'Finland', 'Sweden'};
numRegions = length(cou_nam);
cmap = jet(31); % specify the colormap (with an odd length
cmap(ceil(size(cmap,1)/2),:) = [192 192 192]/255;
% Random vector of values (one for each country)
data = 10*rand(numRegions,1) - 5; % i'm assuming this is a placeholder
datarange = [-5 5]; % nominal data range needs to be symmetric
% rescale the data to use as an index into cmap
coloridx = round((data-min(datarange))/range(datarange) * (size(cmap,1)-1) + 1);
% Map
%figure('Color','w')
xh = worldmap('Europe');
setm(xh,'MapProjection','miller')
tightmap
geoshow('landareas.shp', 'FaceColor', 'white');
for i = 1:1:numRegions
bordersm(cou_nam{i},'facecolor',cmap(coloridx(i),:))
end
colorbar
colormap(cmap) % specify the colormap
caxis(datarange) % needs to match datarange
You will need to make sure that clim() uses the values from nominal range specified by datarange and not the actual extrema of the data. Remember that you're explicitly coloring objects instead of letting the axes apply a scaled colormap. You're basically doing the colormapping yourself, so the colorbar will need to correspond to it, otherwise the colorbar won't reflect the values they're supposed to.

Sign in to comment.

More Answers (0)

Products


Release

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!