9

Is there an easy way to indicate a specific color for each element of a given matrix when using matplotlib. For example, assume we want to show 'x' as follow with three specific colors: red, black, and, white:

enter image description here

However, the only option I found out is using "cmap" which doesn't directly give you the option to "directly" specify the colors.

fig = plt.figure()
ax = fig.add_subplot(111)
x= [[0,0,0,0,0,0],[0,0,0,0,0,0], [0,1,1,2,1,1], [0,0,0,0,0,1], [0,1,1,1,1,1]]    
cax = ax.matshow(x,cmap=plt.cm.gray_r )
plt.show()

enter image description here

My question: how should I change my code to show the above red/black/white grid? [e.g 0 means black, 1 means white, and 2 means red] and in general how we can do it for a larger list of colors? like 10-15 colors.

In addition, how to assign to a certain element in the matix a certain color? for example in above, x[i][j] == 0 then color ='black' or x[i][j] == 2 then color ='red'

Thanks.

superMind
  • 833
  • 2
  • 10
  • 19
  • I recently found an easy solution to this problem. It involves creating a 3d numpy array that represents the desired colors of the data and plotting that rather than the original 2d data array. The solution can be found here https://stackoverflow.com/a/66821752/7871710 – alluppercase Mar 26 '21 at 17:36

1 Answers1

19

You can create your own color maps:

from matplotlib.colors import ListedColormap

cmap = ListedColormap(['k', 'w', 'r'])
cax = ax.matshow(x,cmap=cmap)

enter image description here

If you want to specify 10-15 colors you may run out of single-letter colors. In this case you can specify RGB triplets (e.g. ListedColormap([[0, 0, 0], [1, 1, 1], [1, 0, 0]])) or various other color formats. Alternatively, use one of the pre-defined discrete ("qualitative") color maps listed here.

If the values in the matrix are not consecutive integers you can transform them before plotting.

import numpy as np

x = np.array([[0,0,0,0,0,0],[0,77,0,0,22,0], [0,1,1,2,1,1], [0,0,14,0,0,1], [0,1,1,1,1,1]])
u, i = np.unique(x, return_inverse=True)
y = i.reshape(x.shape)
# array([[0, 0, 0, 0, 0, 0],
#        [0, 5, 0, 0, 4, 0],
#        [0, 1, 1, 2, 1, 1],
#        [0, 0, 3, 0, 0, 1],
#        [0, 1, 1, 1, 1, 1]])
MB-F
  • 22,770
  • 4
  • 61
  • 116
  • 1
    Thanks, @kazemakase. Follow up question, how to assign to a certain element in the matix a certain color? for example in above, x[i][j] == 0 then color ='black' or x[i][j] == 2 then color ='red' – superMind May 11 '17 at 07:58
  • 1
    @superMind I don't fully understand the follow-up. The mapping 0->b, 1->w, 2->r is performed for every element i, j. Do you want special treatment for certain elements? In that case what about the other elements? – MB-F May 11 '17 at 08:35
  • Let's say,x is sth like this: x= [[0,0,0,0,0,0],[0,77,0,0,22,0], [0,1,1,2,1,1], [0,0,14,0,0,1], [0,1,1,1,1,1]] and assume we have 6 colors (c1,c2,c3,c4,c5,c6). The question is that how 0--> c1, 1-->c2, 2-->c3, 14-->c4, 22--> c5, 77-->c6. – superMind May 11 '17 at 09:02
  • 1
    @superMind I think the easiest would be to transform x so that 14->3, 22->4, 77->5. Then the values map nicely to the colors again. I have updated the question to show how this can be done with numpy arrays and the help of `np.unique`. – MB-F May 11 '17 at 09:17
  • Nice, this even works with just a single color and a masked array. – Robert Pollak Mar 10 '21 at 18:01
  • My solution, presented here https://stackoverflow.com/a/66821752/7871710 , is independent of the ordering of the numbers in the original array. I was not able to use this solution for my particular use case. – alluppercase Mar 26 '21 at 17:36