Roger Erismann
Roger Erismann

Reputation: 53

Matplotlib colormap, scatter plot passing a third variable for color: invalid RGBA argument

we are building our reports on matplotlib. Each page has multiple charts and some text.

In the report data there is over 100 locations, each location has a density. The idea is to plot the points on a map where the color (shade of red) represents the density of the location.

However, I do not understand the connection between the kwargs : c and cmap in the ax.scatter call, nor do I understand the role of color.Normalize in this application.

import pandas as pd
import matplotlib
import numpy as np
from pandas import Series, DataFrame
import csv
from scipy import stats
import matplotlib.pyplot as plt
import random
import matplotlib.colors as colors

# Get the data and transform
data = pd.read_csv('logHistThis.csv')
data.drop('Unnamed: 0', axis=1, inplace=True)
dataMean = data['Density'].mean()
data = list(data['Density'])

# I was under the impresion that the data for the colormap
# had to be between 1 and 0 so did this:
aColorScale = []
def myColorScale(theData):
    aColorScale = []
    for x in theData:
        this = x/100
        aColorScale.append(this)
    return aColorScale

aColorScale = myColorScale(data)

estimated_mu, estimated_sigma = stats.norm.fit(data)
xmin = min(data)
xmax = max(data)
x = np.linspace(xmin, xmax, 100)
pdf = stats.norm.pdf(x, loc=estimated_mu, scale=estimated_sigma)

thisRangeMin = np.log(27)
thisRangeMax = np.log(35)

q = [np.random.choice(data, 40)]
z = [ np.random.randint(1, 50, size=40)]
s = 100 *q


colormap = 'Reds'
normalize =matplotlib.colors.Normalize(vmin=xmin, vmax=xmax)
#plt.scatter(x,y,z,s=5, cmap=colormap, norm=normalize, marker='*')


fig = plt.figure(figsize=(10, 5), frameon=False, edgecolor='000000', linewidth = 1)

rect0 = .05, .05, .4, .9
rect1 = .5, .05, .4, .9

# This works great 
ax1 = fig.add_axes(rect0)#<-----------x2TopTenSummary
ax1.hist(data, bins=13, normed=True, color='c', alpha=0.05)
#ax1.fill_between(x, pdf, where=(), alpha=.2)
ax1.fill_between(x, pdf, where=((x <  thisRangeMax) & ( x > thisRangeMin)), alpha=.2, label='City Range')
ax1.vlines(dataMean, 0,  stats.norm.pdf(dataMean, loc=estimated_mu, scale=estimated_sigma), color='r')
ax1.plot(x, pdf, 'k')

# This does not work :
# It just gives blue dots
ax2= fig.add_axes(rect1)
ax2= fig.add_axes(rect1)
ax2.scatter(q,z, s=200,  cmap= 'Reds',norm=matplotlib.colors.Normalize(vmin=min(aColorScale) , vmax=max(aColorScale)))

# Tried to set the color map in a variety of ways:
# When kwarg 'c' is set to the variable 'aColorScale' i get the error

plt.show()
plt.close()

So my question is how do we incorporate the colormap in an application of this sort?

Multiple axes on a figure with a predetermined size (A4 or letter). The color determination is a third variable z, (not x or y) The color determinant is a float where 0 < z < 8 the call is ax not plt

The description of the application in the docs is unclear to me:

the doc for axes.scatter the doc for color.normalize

I have seen plenty of examples where there is only one ax in the figure and the call is to plt.scatter... for example here

In our case x, y will be longitude, lattitude and the variable is 'data' a list or array of floats between 0 and 8.

Thanks

Upvotes: 0

Views: 2064

Answers (2)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339710

While I do have problems understanding the issue itself, I can tell you that the solution you have in your answer can be simplified to the usual way to plot scatters:

ax2= fig.add_axes(rect1)
ax2.scatter(q,z, c=aColorScale, s=200, cmap='Reds')

Upvotes: 0

Roger Erismann
Roger Erismann

Reputation: 53

Okay the answer came from the PyCon Israel 2017 in this document by Tamir Lousky.

The normalization of the data and the correlation with color map happens with this block of code right here:

aColorScale = data
aColorScale = np.array(aColorScale)
norm = (aColorScale - aColorScale.min())/(aColorScale.max() - aColorScale.min())
cmap= plt.get_cmap('Reds')
colors = [cmap(tl) for tl in norm]#<---- thisRightHere

Then colors gets fed into ax2:

ax2= fig.add_axes(rect1)
ax2.scatter(q,z, s=200, color = colors)

I wish those who downvoted my question would say why, there was hours of searching and trying to find this.

Anyway here is the final image:

enter image description here

Upvotes: 1

Related Questions