3

I am trying to add ticks and labels to a color bar, but it just doesn't seem to show up in the output. I have tried two approaches(as shown in the code below). Second appraoch was to do as shown in another question on Stack Overflow here: How to add Matplotlib Colorbar Ticks.

I must be overlooking something very simple here as I am a beginner in Matplotlib and Python.

I have managed to obtain the color bar, but the ticks I want just don't show up. Any help here will be greatly appreciated as I have been stuck at it for hours after trying and searching. Here is the code I used to generate a heatmap using hexbin over a basemap.

import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib.colors import LinearSegmentedColormap
from matplotlib import cm

#Loading data from CSV file
DATA_FILE = '....../Population_data.csv'
roc_data = pd.read_csv(DATA_FILE)
roc_data.head()

#Creating figure window
fig = plt.figure(figsize=(14,10))
ax = fig.add_subplot(111)

#Drawing the basemap
m = Basemap(projection='merc', lat_0=43.12, lon_0=-77.626,
resolution = 'i',llcrnrlon=-78.236, 
                llcrnrlat=42.935,
                urcrnrlon=-77.072, 
                urcrnrlat=43.349)
m.drawcoastlines()
m.drawcounties(zorder=20, color='red')
m.drawcountries()
m.drawmapboundary()

#plotting the heatmap using hexbin
x, y = m(roc_data['Longitude'].values, roc_data['Latitude'].values)
values = roc_data['Total(20-64)']
m.hexbin(x, y, gridsize = 125, bins = 'log', C = values, cmap = cm.Reds)


#Defining minimum, mean and maximum population values
max_p = roc_data['Total(20-64)'].max()
min_p = roc_data['Total(20-64)'].min()
mean_p = roc_data['Total(20-64)'].mean()

#Adding Colorbar
cb = m.colorbar(location = 'bottom', format = '%d', label = 'Population by Census Blocks')

#setting ticks

#cb.set_ticks([48, 107, 1302])                #First approach, didn't work 
#cb.set_ticklabels(['Min', 'Mean', 'Max'])

cb.set_ticks([min_p, mean_p, max_p])          #Second appraoch, assumed ticks and tick labels should be same
cb.set_ticklabels([min_p, mean_p, max_p])     #from the above mentioned stackoverflow question, but did't work

plt.show()

The output I get by using the first or second approach for colorbar ticks is the same. It is as here: Heatmap and colorbar with no ticks and labels

I want the minimum, median and maximum population values (48, 107 and 1302) to be shown on the colorbar with the labels Min, Mean and Max. Thank you for your time

Community
  • 1
  • 1
bartman
  • 33
  • 5

1 Answers1

0

When plotting the hexbin plot with mode bins = 'log', the colors will be plotted with a logarithmic scaling. This means that if the data minimum, mean and maximum are min, mean and max, their values on the logarithmically scaled colorbar are log10(min), log10(mean), log10(max).

The ticks on the colorbar therefore needs to be set with the log values. The ticklabels can be set to any value. However I would think that simply putting something like "mean" on a logarithmic scale may not be too informative.

A particularity is that the minimum of the colorbar is actually log10(min+1). The +1 is due to the log which is negative below 1.

Here is a complete example.

enter image description here

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
from mpl_toolkits.basemap import Basemap
from matplotlib import cm

lon = -78.236+np.random.rand(1000)*(-77.072+78.236)
lat = 42.935 + np.random.rand(1000)*(43.349-42.935)
t = 99+np.random.normal(10,20,1000)
t[:50] = np.linspace(48,1302)
roc_data = pd.DataFrame({'Longitude':lon, 'Latitude':lat, "T":t })


#Creating figure window
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111)

#Drawing the basemap
m = Basemap(projection='merc', lat_0=43.12, lon_0=-77.626,
resolution = 'i',llcrnrlon=-78.236, 
                llcrnrlat=42.935,
                urcrnrlon=-77.072, 
                urcrnrlat=43.349)
m.drawcoastlines()
m.drawcounties(zorder=20, color='red')
m.drawcountries()
m.drawmapboundary()

#plotting the heatmap using hexbin
x, y = m(roc_data['Longitude'].values, roc_data['Latitude'].values)
values = roc_data['T']
m.hexbin(x, y, gridsize = 125, bins = 'log', C = values, cmap = cm.Reds) #bins = 'log',

#Defining minimum, mean and maximum population values
max_p = roc_data['T'].max()
min_p = roc_data['T'].min()
mean_p = roc_data['T'].mean()
print [min_p, mean_p, max_p]
print [np.log10(min_p), np.log10(mean_p), np.log10(max_p)]

#Adding Colorbar
cb = m.colorbar(location = 'bottom', format = '%d', label = 'Population by Census Blocks') #format = '%d',

#setting ticks 
cb.set_ticks([np.log10(min_p+1), np.log10(mean_p), np.log10(max_p)])          
cb.set_ticklabels(['Min\n({:.1f})'.format(min_p), 'Mean\n({:.1f})'.format(mean_p), 'Max\n({:.1f})'.format(max_p)])
plt.tight_layout()
plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • That is exactly what I was looking for. I missed converting the values to log10 and didn't know that the minimum of the colorbar is actually log10(min+1). Thanks! – bartman Mar 06 '17 at 06:40
  • Great, so if this answered your question, consider [accepting](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) and upvoting it. – ImportanceOfBeingErnest Mar 06 '17 at 07:36
  • Hi again, thanks for letting me know about accepting answers here, didn't know about it. I tried upvoting it but seems it will not be publicly displayed unless I have a reputation of more than 15, although my upvote will be recorded. I will again upvote it after my reputation goes above 15. – bartman Mar 12 '17 at 00:44
  • Your upvote will be recorded and will appear as soon as you reach 15 reputation. No need to revisit old questions. – ImportanceOfBeingErnest Mar 12 '17 at 08:20