3

I am trying to plot a scatter plot where each point in the scatter plot should correspond to a particular shade of a given color of my choice. The mpl documentation states that if I set something like:

color = '0.7'

it gives me a shade of grey with that scaled intensity of 0.7. I am reading the intensity of the colours from an array with values between 0 and 1 and each value corresponds to the intensity of that point in the scatter plot. My code below is as follows:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import math

tsne_embeddings = np.load("tsne_embeddings.npy")
labels = np.load('labels.npy')
weights = np.load('weights.npy')
# Scale the weights from 0 to 1
max_weight = max(weights)
min_weight = min(weights)
weights = (weights - min_weight)/(max_weight - min_weight)
print(tsne_embeddings.shape)
x = list(tsne_embeddings[:,0])
y = list(tsne_embeddings[:,1])
labels = list(labels)

weights = np.round(weights,decimals=2)
weights = (np.exp(weights) - 1)/(np.exp(1) - 1)
weights = list(weights)
print(min(weights),max(weights))

for i, shade in enumerate(weights):
    plt.scatter(x[i],y[i],color=shade,marker = '+')

plt.show()

I am scaling those weights exponentially hoping for a better variation. So, essentially, my questions are:

  1. How do I change the color to say shades of blue or red or green as opposed to just greyscale?
  2. Is the approach which I follow for greyscale correct?

Thank you!

Megh
  • 67
  • 1
  • 1
  • 7

2 Answers2

7

To make your approach work for shades of grey, you need to convert the value to a string, so plt.scatter(..., color=str(shade)).

The more standard way of working with matplotlib would be to directly use the weights, without rescaling them to the range 0 to 1, use a colormap, and calling scatter directly with the arrays. The weights go into the c= parameter. For grey values this would be plt.scatter(x, y, c=weights, cmap='Greys', marker='+'). An additional feature of matplotlib is that with this information it can automatically create a colorbar mapping the grey values to the corresponding weight. If only one scatter plot is created, plt.colorbar() without parameters will show this colorbar.

Similar colormaps exist of 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds', ... See the official doc with a complete list. If the range between light and dark goes the wrong way, appending '_r' to the name will use the opposite color range (so, 'Greys' goes from white to black, while 'Greys_r' goes from black to white).

Here is a working example using the values from 1 to 10 for the three arrays:

from matplotlib import pyplot as plt
import numpy as np

x = np.arange(1, 11)
y = np.arange(1, 11)
weights = np.arange(1, 11)
plt.scatter(x, y, c=weights, cmap='Greys', marker='+')
plt.colorbar()
plt.show()

example plot

JohanC
  • 71,591
  • 8
  • 33
  • 66
1

You can use colormaps in python to generate different shades of blue green etc. https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html I am using Blues color map here

import matplotlib.pyplot as plt
import matplotlib as mpl
norm = mpl.colors.Normalize(vmin=min(weights), vmax=max(weights))
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.Blues)
for i, xi in enumerate(x):
    plt.scatter(x[i],y[i],color=cmap.to_rgba(i+1),marker = '+')
plt.show()
Ajay Verma
  • 610
  • 2
  • 12
  • 1
    Thanks a lot! How do I exactly pass my weights? Or is that passed automatically in the norm = mpl.colors. ......... line, when the max and min is called? Basically my question is how does my `scatter` know from where tp pick the weights? – Megh Sep 22 '20 at 06:45