0

How do I use matplotlib.pyplot to colour the background of my plot based on an array (of True/False's)?

So for example, if my array was (T,F,F,F,T,T) and I choose the colours 'red' and 'blue', I need the background to be a red column, 3 blue colomns, followed by 2 more reds.

N = 2000
tf = np.random.normal(size = N)
ctf = np.array([np.sum(tf[:1+i]) for i in range(N)])
fig, ax = plt.subplots()
tf2 = tf[None,:]
ax.imshow(tf2, cmap='RdYlGn', aspect = 'auto')
ax.plot(ctf,'k')
  • Take a look at `pcolor` or `imshow`. Make sure your input is 2 dimensional though (even if one dimension is only 1) – busybear Dec 13 '18 at 21:53

2 Answers2

2

You can use imshow:

import numpy as np
from matplotlib import pyplot as plt
fig, ax = plt.subplots()
data = np.array([True, False, True])[ None, :]
ax.imshow(data, cmap = 'RdBu', aspect="auto")
ax.axis('off')
fig.show()

edit: swapped axis to produce columns edit2: add larger imshow

import numpy as np
from matplotlib import pyplot as plt
N = 2000
tf = np.random.normal(size = N)
ctf = np.array([np.sum(tf[:1+i]) for i in range(N)])
fig, ax = plt.subplots(2, sharex = 'all', \
                       gridspec_kw = dict(\
                                         height_ratios = [5, 1]))
tf2 = tf[None,:]
ax[0].plot(ctf,'k')
ax[1].imshow(tf2, cmap='RdYlGn', aspect = 'auto')
plt.subplots_adjust(hspace = 0)

edit 3:

import numpy as np
from matplotlib import pyplot as plt
N = 2000
tf = np.random.normal(size = N)
ctf = np.array([np.sum(tf[:1+i]) for i in range(N)])
fig, ax = plt.subplots()

tf2 = tf[None,:]
ax.plot(ctf,'k')
ax.imshow(tf2, cmap='RdYlGn', aspect = 'auto', extent =[0, ctf.shape[0], ctf.min(), ctf.max()])

enter image description here enter image description here

enter image description here

cvanelteren
  • 1,633
  • 9
  • 16
  • Is this supposed to work with a really long array for Data? I tried and it gives me just a line – qwerty asdf Dec 13 '18 at 22:33
  • Yes, but depending on the size of the array the resolution may not scale. I would recommend scaling the imshow with either scale = 'auto' or resizing the plot. Alternatively you may want to use multiple columns if the data is really long. This can be achieved by providing a 2d array as input to imshow. – cvanelteren Dec 13 '18 at 22:37
  • You will want to use `aspect="auto"`. I took the freedom to edit the answer. – ImportanceOfBeingErnest Dec 13 '18 at 22:41
  • I get 'AttributeError: Unknown property scale'. edit: just saw your edit. Let me try that. – qwerty asdf Dec 13 '18 at 22:43
  • Yes my bad, meant aspect. – cvanelteren Dec 13 '18 at 22:44
  • Thanks. That work. However when I try to draw another plot on top the height of the columns stays the same. This makes it look like a coloured line because the plot on top goes from -10 to 10. How can I fix that? – qwerty asdf Dec 13 '18 at 22:51
  • Is this on the same axis or on a different one? Can you include the code above? – cvanelteren Dec 13 '18 at 22:55
  • Also, why is the y-axis upside-down? It goes from -0.5 at the bottom to 0.5 at the top. – qwerty asdf Dec 13 '18 at 23:16
  • The reason why it is so small is that the imshow data is plotted on the range(0,1) since it only has one row. I am not entirely sure what you want to plot. But you can either create two axis to enlarge the imshow, or create vertical markers on the graph. Edited my code above – cvanelteren Dec 13 '18 at 23:17
  • What I wanted is plotting ctf with a multicoloured background. The background would indicate the regions where ctf is increasing or decreasing. However what you did works too. Thanks a lot for your time. – qwerty asdf Dec 13 '18 at 23:31
  • omg! Thank you so much. That's exactly what I wanted. I wish I could upvote twice. – qwerty asdf Dec 13 '18 at 23:48
0

Sounds like you want to draw rectangles on your plot. (See matplotlib: how to draw a rectangle on image) If you want to have the Rectangles behind some other data, set their zorder to a negative number when you create them.