11

I have a code that gives me a scatter plot of predicted vs actual values as a function of concentration. The data is pulled from an excel csv spreadsheet.

This is the code:

import matplotlib.pyplot as plt
from numpy import loadtxt


dataset = loadtxt("ColorPlot.csv", delimiter=',')
x = dataset[:,0]
y = dataset[:,1]
z = dataset[:,2]

scaled_z = (z - z.min()) / z.ptp()

colors = plt.cm.viridis(scaled_z)
sc=plt.scatter(x, y, c=colors)
plt.clim(0, 100)
plt.colorbar()
plt.xlabel("Actual")
plt.ylabel("Predicted")

plt.show()

And with this I get a nice graph: enter image description here

However if I change the color to something like

colors = plt.cm.plasma(scaled_z)

I get the graph below but the colorbar remains unchanged.

enter image description here

I've tried lots of different things like cmap or edgecolors but I don't know how to change it. And I want to keep the code as simple as it currently is because I want to readily change the third variable of z based on my excel spreadsheet data.

Is there also a way for the scale of the colorbar to pick up what the scale is from the excel spreadsheet without me manually specifying 0-100?

2
  • 3
    The standard way is to call it as plt.scatter(x, y, c=z, cmap='plasma'). And leaving out plt.clim(). In that standard way, the colorbar will get the 'plasma' colors, and will have indications of the lowest and highest z values. If, instead, you want the colorbar to go between 0 and 100, you could do scaled_z = 100*(z - z.min()) / z.ptp() and plt.scatter(x, y, c=scaled_z, cmap='plasma'). In any case, it is best to leave out plt.clim() Commented Sep 21, 2020 at 16:11
  • Omg thats perfect. Literally solved it straight away. Thanks so much. I removed the scaled z term, put cmap in the scatter term and removed plt.clim(). Perfect thanks @JohanC Commented Sep 21, 2020 at 16:40

4 Answers 4

12

To get the right color bar, use the following code:

colormap = plt.cm.get_cmap('plasma') # 'plasma' or 'viridis'
colors = colormap(scaled_z)
sc = plt.scatter(x, y, c=colors)
sm = plt.cm.ScalarMappable(cmap=colormap)
sm.set_clim(vmin=0, vmax=100)
plt.colorbar(sm)
plt.xlabel("Actual")
plt.ylabel("Predicted")
plt.show()

For my random generated data I got the following plot:

enter image description here

Now replace 'plasma' with 'viridis' and check the other variant.

Sign up to request clarification or add additional context in comments.

Comments

1

You should not scale your data, unless you want the colorbar to be incorrect. Once you have the PathCollection from the scatter call, you can call set_cmap and set_clim on that and the colorbar should track. (you could also explicitly associate the colorbar with the PathCollection to avoid ambiguity)

import matplotlib.pyplot as plt
import numpy as np


x = np.random.randn(100)
y = np.random.randn(100)
z = np.random.randn(100)

sc=plt.scatter(x, y, c=z, cmap='viridis')
plt.clim(0, 100)
plt.colorbar(sc)
plt.xlabel("Actual")
plt.ylabel("Predicted")
sc.set_cmap('plasma')
sc.set_clim(-1, 1)

plt.show()

enter image description here

Comments

0

Your code return for me an error TypeError: You must first set_array for mappable ...

The following is a simplest syntax that works for me:

import matplotlib.pyplot as plt
import numpy as np

a = np.random.random(100)
b = np.random.random(100)

scaled_z = (a + b)/a

plt.figure()
plt.scatter(a, b, c = scaled_z, cmap = 'plasma') ## you can directly change the colormap here
plt.colorbar()
plt.tight_layout()
plt.show()

Comments

0

Simply use the cmap keyword.

x = np.random.randn(100)
y = np.random.randn(100)
c = np.random.randn(100)

plt.scatter(x, y, c=c, cmap='plasma')
plt.colorbar()

Unfortunately, edgecolors would need more work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.