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')
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()])
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.
Related
I am trying to visualize the features obtained from TSNE. I have two questions:
Why am I getting viridis in color bar even though I have specified another cmap?
I want to use the cmap colors to plot the features for all images in a 3d plot. I want to use a single color for all 256 coordinates of a single image. Is the below code correctly doing so?
Below is the code I am using:
import numpy as np
import matplotlib.pyplot as plt
cmap = plt.cm.get_cmap('plasma', 1000)
i = 0
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
features = np.random.rand(1000, 256, 2)
for fvec in features:
if(i%50 == 0):
x_coord, y_coord = fvec.T
p = ax.scatter(i, x_coord, y_coord, color=cmap(i))
i = i+1
fig.colorbar(p)
plt.show()
This is the output that I am getting.
EDIT: First question is solved with help from comments.
Clarification on second question:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
features = np.random.rand(1, 100, 2)
i = 0
for fvec in features:
x_coord, y_coord = fvec.T
p = ax.scatter(i, x_coord, y_coord, c=i*np.ones(len(x_coord)), norm=plt.Normalize(0,1), cmap='plasma')
i = i+1
fig.colorbar(p)
plt.show()
In this, among the 100 points plotted, some are of a darker color and some lighter. Are all points not using the same color?
See the output here
Assume we have a heat-map as below
construct using the code
import string
import numpy as np
from matplotlib import pyplot as plt
label=list(string.ascii_uppercase)
mdata = np.random.randn(3, len(label), len(label))
data = mdata[0, :, :]
data=np.tril(data,-1)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Blues)
plt.show()
Is possible whether using Matplotlib, Seaborn or any other package to render into isometric
alignment as below.
With matplotlib's 3D toolkit, and using numpy's triu_indices, you could create a bar plot from the triangular matrix:
import numpy as np
import matplotlib.pyplot as plt
ax = plt.figure().add_subplot(projection='3d')
N = 26
data = np.random.randn(3, N, N)
for i, (plane, cmap) in enumerate(zip(data, ['Reds', 'Greens', 'Blues'])):
indices = np.triu_indices(N, 1)
norm = plt.Normalize(plane.min(), plane.max())
ax.bar(left=indices[0], bottom=indices[1], height=0.9,
zs=i, zdir='y',
color=plt.get_cmap(cmap)(norm(plane[indices])))
plt.show()
PS: To have full rectangles, the sub-arrays from np.indices need to be made 1D:
import numpy as np
import matplotlib.pyplot as plt
ax = plt.figure().add_subplot(projection='3d')
N = 26
data = np.random.randn(3, N, N)
for i, (plane, cmap) in enumerate(zip(data, ['Reds', 'Greens', 'Blues'])):
indices = np.indices((N,N))
norm = plt.Normalize(plane.min(), plane.max())
ax.bar(left=indices[0].ravel(), bottom=indices[1].ravel(), height=0.9,
zs=i, zdir='y',
color=plt.get_cmap(cmap)(norm(plane).ravel()))
plt.show()
How could I get a different pie chart color? I have a data set about 20 categories and it could be even larger. When I create a pie chart, some wedge have same color, so I wonder is there a way that I can have all colors different in my pie charts' wedge?
Thanks!
20 Colors is exactly the limits of what you can achieve through categorical/qualitative colormaps in matplotlib. Currently matplotlib provides the tab20, tab20b, tab20c colormaps.
import matplotlib.pyplot as plt
import numpy as np
data = np.random.randint(50,200, size=20)
fig = plt.figure()
with plt.style.context({"axes.prop_cycle" : plt.cycler("color", plt.cm.tab20.colors)}):
ax = fig.add_subplot(121, aspect="equal")
ax.pie(data)
with plt.style.context({"axes.prop_cycle" : plt.cycler("color", plt.cm.tab20c.colors)}):
ax2 = fig.add_subplot(122, aspect="equal")
ax2.pie(data)
plt.show()
For more colors one can of course also use different colormaps, but those will generally result in pretty similar colors next to each other. E.g. for a pie chart with 30 different colors we may use the nipy_spectral or the CMRmap colormap.
import matplotlib.pyplot as plt
import numpy as np
data = np.random.randint(50,200, size=30)
fig = plt.figure()
cc = plt.cycler("color", plt.cm.nipy_spectral(np.linspace(0,.9,len(data))))
with plt.style.context({"axes.prop_cycle" : cc}):
ax = fig.add_subplot(121, aspect="equal")
ax.pie(data)
cc = plt.cycler("color", plt.cm.CMRmap(np.linspace(0,0.9,len(data))))
with plt.style.context({"axes.prop_cycle" : cc}):
ax2 = fig.add_subplot(122, aspect="equal")
ax2.pie(data)
plt.show()
So one may add another dimension. Choosing some colors from any colormap and creating different luminosity levels for each of them. This is essentially shown in this answer. Here, in order to get e.g. 30 different colors we may choose 6 colors and for each 5 luminosity levels.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors
def categorical_cmap(nc, nsc, cmap="tab10", continuous=False):
if nc > plt.get_cmap(cmap).N:
raise ValueError("Too many categories for colormap.")
if continuous:
ccolors = plt.get_cmap(cmap)(np.linspace(0,1,nc))
else:
ccolors = plt.get_cmap(cmap)(np.arange(nc, dtype=int))
cols = np.zeros((nc*nsc, 3))
for i, c in enumerate(ccolors):
chsv = matplotlib.colors.rgb_to_hsv(c[:3])
arhsv = np.tile(chsv,nsc).reshape(nsc,3)
arhsv[:,1] = np.linspace(chsv[1],0.25,nsc)
arhsv[:,2] = np.linspace(chsv[2],1,nsc)
rgb = matplotlib.colors.hsv_to_rgb(arhsv)
cols[i*nsc:(i+1)*nsc,:] = rgb
cmap = matplotlib.colors.ListedColormap(cols)
return cmap
data = np.random.randint(50,200, size=30)
fig = plt.figure()
cc = plt.cycler("color", categorical_cmap(6, 5, cmap="tab10").colors)
with plt.style.context({"axes.prop_cycle" : cc}):
ax = fig.add_subplot(121, aspect="equal")
ax.pie(data)
cc = plt.cycler("color",
categorical_cmap(6, 5, cmap="gist_rainbow", continuous=True).colors)
with plt.style.context({"axes.prop_cycle" : cc}):
ax2 = fig.add_subplot(122, aspect="equal")
ax2.pie(data)
plt.show()
I have the following strange behavior: When I limit the range of the figure, the colorplot shows it nevertheless:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.linspace(0,1,100)
X,Y = np.meshgrid(x,x,indexing="ij")
im = ax.contourf(X,Y,X**2-Y**2, 100, vmin = 0, vmax = 0.5)
plt.colorbar(im, ax=ax)
plt.show()
how can I configure the limits of the colorbar correctly?
The 100 within the ax.contourf() means that you want 100 levels within the contour. You do have values that go over 0.5 within the plot itself.
You can customize the range of the color bar ticks as such.
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
cbarticks = np.arange(0.0,0.55,0.05)
x = np.linspace(0,1,100)
X,Y = np.meshgrid(x,x,indexing="ij")
im = ax.contourf(X,Y,X**2-Y**2, cbarticks, vmin = 0, vmax = 0.5)
plt.colorbar(im, ax=ax,ticks=cbarticks)
plt.show()
which will give you
Unsure if this is exactly what you want but I had a similar question and answered it myself here: Colorbar Question
I'm trying to plot 23 graphs in a 6x4 grid, with one figure taking up twice the width of the other figures. I'm using gridspec and my current code is:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec
x = np.arange(0, 7, 0.01)
fig = plt.figure(figsize=(6, 4))
gs = gridspec.GridSpec(nrows=6, ncols=4)
for n in range(22):
ax = fig.add_subplot(gs[n])
ax.plot(x, np.sin(0.2*n*x))
corrax = fig.add_subplot(gs[22])
fig.tight_layout()
plt.show()
This produces the following:
I want to increase the width of the rightmost plot in the bottom row so it takes up the remaining space in that row. Is there a way to accomplish this?
You can use slices to select several positions from the gridspec, e.g. gs[22:24].
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec
x = np.arange(0, 7, 0.01)
fig = plt.figure(figsize=(6, 4))
gs = gridspec.GridSpec(nrows=6, ncols=4)
for n in range(22):
ax = fig.add_subplot(gs[n])
ax.plot(x, np.sin(0.2*n*x))
corrax = fig.add_subplot(gs[22:24])
corrax.plot(x,np.sin(0.2*22*x), color="crimson", lw=3)
fig.tight_layout()
plt.show()
You can also slice the gridspec two-dimensionally. E.g. to create a 3x3 grid and make the plot in the lower right corner span two columns and two rows, you could slice like gs[1:,1:].
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec
x = np.arange(0, 7, 0.01)
fig = plt.figure(figsize=(6, 4))
gs = gridspec.GridSpec(nrows=3, ncols=3)
for n in range(3):
ax = fig.add_subplot(gs[0,n])
ax.plot(x, np.sin(0.2*n*x))
if n !=0:
ax = fig.add_subplot(gs[n,0])
ax.plot(x, np.sin(0.2*n*x))
corrax = fig.add_subplot(gs[1:,1:])
corrax.plot(x,np.sin(0.2*22*x), color="crimson", lw=3)
fig.tight_layout()
plt.show()
#corrax = fig.add_subplot(gs[5,2:])
corrax = fig.add_subplot(6,4,(23,24))
both shold work.
see examples