I am using matplotlib table to create a heatmap that contains different values. While creating the table, ticks are not aligned at the center of each cell in both x-axis and y-axis.
I want to create something like this.
But rather I am getting ticks that are not uniform in both axes. Ticks starts at the middle of the cell from bottom-left column and gets distorted while moving to top and right cell.
I am using this code to generate this matplotlip table.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import os
import sys
from matplotlib.table import Table
fig,ax=plt.subplots(figsize=(15,15))
tb = Table(ax,bbox=[0,0,1,1])
nrows, ncols = 20,20
width, height = 1.0 / ncols, 1.0 / nrows
headers = 20
data = np.zeros((nrows, ncols))
ax.set_xticks(np.arange(0.5,headers+0.5))
ax.set_yticks(np.arange(0.5,headers+0.5))
ax.xaxis.set_tick_params(labelsize=12)
ax.yaxis.set_tick_params(labelsize=12)
for (i,j),val in np.ndenumerate(data):
tb.add_cell(i, j, width, height)
tb.add_cell(i, j, width, height, loc='center')
tb.auto_set_font_size(False)
tb.set_fontsize(15)
ax.add_table(tb)
ax.set_aspect('equal')
plt.show()
Is there anything I am missing?
this will do the work
plt.ylim(0,headers)
plt.xlim(0,headers)
also adding this line plt.xticks(rotation=90) will help you rotate values in the xaxis and avoid overlapping
full program will be like
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import os
import sys
from matplotlib.table import Table
fig, ax = plt.subplots(figsize=(15, 15))#
tb = Table(ax, bbox=[0, 0, 1, 1])
nrows, ncols = 20,20
width, height = 1.0 / ncols, 1.0 / nrows
headers = 20
data = np.zeros((nrows, ncols))
ax.set_xticks(np.arange(0.5,headers+0.5))
ax.set_yticks(np.arange(0.5,headers+0.5))
plt.ylim(0,headers)
plt.xlim(0,headers)
plt.xticks(rotation=90)
ax.xaxis.set_tick_params(labelsize=12)
ax.yaxis.set_tick_params(labelsize=12)
for (i, j), val in np.ndenumerate(data):
tb.add_cell(i, j, width, height)
tb.add_cell(i, j, width, height, loc='center')
tb.auto_set_font_size(False)
tb.set_fontsize(15)
ax.add_table(tb)
ax.set_aspect('equal')
plt.show()
output
Have you heard of seaborn? This is a plotting library built on top of matplotlib that takes care of those things for you. They have a function heatmap which does exactly this, and handles the placing of the ticks automatically: https://seaborn.pydata.org/generated/seaborn.heatmap.html#seaborn.heatmap
Example:
import seaborn as sns
ax = sns.heatmap(np.zeros(20,20))
plt.show()
gives this:
You can then play with the ticklabels and modify them at will like you would do on any matplotlib plot. For example, ax.set_xticklabels(np.arange(0.5, 20, 0.5)) will rename your x-ticks like on your picture.
The answers have been accepted through a lot of trial and error, but we're changing the idea and color mapping. How about customizing it and using a heat map to solve the problem? It would be convenient to process various things. I will share it with you for your reference.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
mat = np.random.rand(10,10)
# RGB -> Hex
# ['rgb(0,0,205)', 'rgb(50,205,50)', 'rgb(255,69,0)'] -> ['#0000cd', '#32cd32', '#ff4500']
# ['mediumblue', 'limegreen', 'orangered'])
rgb_c = [(0,0,205), (50,205,50), (255,69,0)]
# RGB convert to Hex
cols = ['#%02x%02x%02x' % (c[0],c[1],c[2]) for c in rgb_c]
cm = matplotlib.colors.ListedColormap(cols)
fig, ax = plt.subplots()
heatmap = ax.pcolor(mat, cmap=cm)
ax.set_aspect('equal')
plt.show()
Related
I want to do an animated scatter plot with one only pair of x,y data for each frame.
The code I wrote creates an animated scatter plot but the old dots appear in the plot, that means that new dots are added on the plot, keeping the old ones.
For the code below I want a dot per frame like a moving dot on x axis and not adding one more value.
I tried with plt.clf() but then all data disappear.
%matplotlib notebook
from bokeh.plotting import figure, output_file, show
import pandas
import numpy as np
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation, PillowWriter
import matplotlib.pyplot as plt
writer = PillowWriter(fps=10)
list_x=[1,2,3,4,5,6,7,8,9]
list_y=[5,5,5,5,5,5,5,5,5]
def plot(listax, listay):
plt.scatter(listax, listay, c='blue', alpha=0.5)
plt.show()
fig2 = plt.figure()
plt.xlim([0, 10])
plt.ylim([0, 10])
with writer.saving(fig2, "plotvideo.gif", 100):
for i in range(0, len(list_x)):
x_value = list_x[i]
y_value = list_y[i]
writer.grab_frame()
plot(x_value, y_value)
Use the .remove() method on the point objects to remove them from the figure.
I would try this:
from bokeh.plotting import figure, output_file, show
import pandas
import numpy as np
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation, PillowWriter
import matplotlib.pyplot as plt
import time
writer = PillowWriter(fps=10)
list_x=[1,2,3,4,5,6,7,8,9]
list_y=[5,5,5,5,5,5,5,5,5]
points = []
def plot(listax, listay, j):
points.append(plt.scatter(listax[j], listay[j], c='blue', alpha=0.5))
if len(points) == 2:
points[0].remove()
points.pop(0)
plt.show(block=False)
fig2 = plt.figure()
plt.xlim([0, 10])
plt.ylim([0, 10])
with writer.saving(fig2, "plotvideo.gif", 100):
for i in range(0, len(list_x)):
x_value = list_x
y_value = list_y
writer.grab_frame()
print(points)
plot(x_value, y_value, i)
See this link for a better explanation (albeit with a different implementation):
How to remove points from a plot?
I want to make a 3x2 subplot image in python. With the images in third row I have added a colorbar. But it the image size gets small as compared to the top rows. Is there anyway to fix the image size the same as of top two rows while having a colorbar in the third row?
Here's my python code
#Imports
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import matplotlib.image as image
import matplotlib.colors
from matplotlib.colors import ListedColormap
#data
bird = image.imread('Desktop/bird.jpeg')
fig, (ax1, ax2, ax3) = plt.subplots(3,2,figsize=(5,5))
ax1[0].imshow(bird)
ax1[0].set_ylabel('Row 1', size=8)
ax1[0].set_yticks([]) #display no ticks
ax1[0].set_xticks([])
ax1[1].imshow(bird)
ax1[1].set_yticks([])
ax1[1].set_xticks([])
ax2[0].imshow(bird)
ax2[0].set_yticks([])
ax2[0].set_xticks([])
ax2[0].set_ylabel('Row 2', size=8)
ax2[1].imshow(bird)
ax2[1].set_yticks([])
ax2[1].set_xticks([])
#Generating Color Map
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", ["Red","Green","Blue"])
# Right Image
bird_3 = ax3[1].imshow(bird, cmap = cmap)
ax3[1].set_yticks([])
ax3[1].set_xticks([])
cbar_int = fig.colorbar(bird_3,orientation='horizontal', ax=ax3[1])
cbar_int.set_label('CBar', size=8, rotation=0)
cbar_int.ax.tick_params(labelsize=8)
bird_3.set_clim(vmin=-1, vmax=1)
# Left Image
bird_4 = ax3[0].imshow(bird, cmap = cmap)
ax3[0].set_yticks([])
ax3[0].set_xticks([])
ax3[0].set_ylabel('Row 3', size=8)
cbar_int = fig.colorbar(bird_4,orientation='horizontal', ax=ax3[0])
cbar_int.set_label('CBar', size=8, rotation=0)
cbar_int.ax.tick_params(labelsize=8)
bird_3.set_clim(vmin=-1, vmax=1)
plt.show()
The following results I get with it. You see row 3 images are small compared to row 1 and 2.
Matplotlib steals space from the host axes. However, you can specify more than one axes to steal space from. So above you can easily do:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
fig, axs = plt.subplots(3, 2)
for ax in axs.flat:
pc = ax.imshow(np.random.randn(20,40))
fig.colorbar(pc, ax=axs[:, 1], orientation='horizontal')
fig.colorbar(pc, ax=axs[:, 0], orientation='horizontal')
plt.show()
and space is stolen from all three axes in each column.
You can also specify constrained_layout=True for slightly better layout.
Note that with imshow the axes have a fixed aspect ratio, so there is always going to be issues with white space.
I am pretty much a beginner in using python's matplotlib library.
I have ten plots to be drawn in the same figure, using matplotlib.pyplot.plot assigns. I would like to pick the colors from a ranger "shorter" than the default one, for example "around the red" (like from reddish purple to orange). Is it possible? How can I do it in python?
I also found this https://matplotlib.org/examples/color/colormaps_reference.html, but it seems quite useless to me.
Thanks for answering
EDIT: to better clarify what I need, I am looking for a way to communicate to the "plt.plot" function that I want it to iterate over a different set of colors
If you want to create a color ramp you can do the following. Using https://matplotlib.org/3.2.1/tutorials/colors/colormap-manipulation.html as a reference:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
def plot_examples(colormaps):
"""
Helper function to plot data with associated colormap.
"""
np.random.seed(19680801)
data = np.random.randn(30, 30)
n = len(colormaps)
fig, axs = plt.subplots(1, n, figsize=(n * 2 + 2, 3),
constrained_layout=True, squeeze=False)
for [ax, cmap] in zip(axs.flat, colormaps):
psm = ax.pcolormesh(data, cmap=cmap, rasterized=True, vmin=-4, vmax=4)
fig.colorbar(psm, ax=ax)
plt.show()
colors = ["purple", "red"]
cmap1 = LinearSegmentedColormap.from_list("mycmap", colors)
plot_examples([cmap1])
You can also use the colormap to get values for a normal plot:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
# Creating the colar map
colors = ["purple", "red"]
cmap1 = LinearSegmentedColormap.from_list("mycmap", colors)
# Data used in plot
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
plt.plot(t, s, color=cmap1(0.1))
plt.show()
Here you can change the 0.1 in the second to last line to choose where on the colormap you want to query (0-255).
I'm trying to draw a rectangle in matplotlib using the following code:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
width = 20
height = 10
rect = patches.Rectangle((0,0),width, height, linewidth=4,edgecolor='r',facecolor='none')
ax.add_patch(rect)
plt.show()
Which results in:
The axes do not fit the rectangle limits in this case. I could solve it with:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
width = 20
height = 10
ax.set_xlim(0,width)
ax.set_ylim(0,height)
rect = patches.Rectangle((0,0),width, height, linewidth=4,edgecolor='r',facecolor='none')
ax.add_patch(rect)
plt.show()
This gives me the following picture which solves the problem in this case:
However, as I am trying to plot many rectangles and other shapes in the same figure, I need a way that matplotlib smartly determines the proper axes limits itself, like the way it does when plotting normal diagrams.
You are looking for .autoscale(). You may use .margins(0) to remove any extra space that is added by default.
I.e.
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
width = 20
height = 10
rect = patches.Rectangle((0,0),width, height, linewidth=4,edgecolor='r',facecolor='none')
ax.add_patch(rect)
ax.margins(0)
ax.autoscale()
plt.show()
I'm trying to make a grid of images in matplotlib using gridspec. The problem is, I can't seem to get it to get rid of the padding between the rows.
Here's my attempt at the solution.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import ImageGrid
import numpy as np
from os import listdir
from os import chdir
from PIL import Image
import matplotlib.gridspec as gridspec
chdir('/home/matthew/Dropbox/Work/writing/'+
'paper_preperation/jump_figs')
files = listdir('/home/matthew/Dropbox/Work/writing/'+
'paper_preperation/jump_figs')
images = [Image.open(f) for f in files]
"""
fig = plt.figure()
grid = ImageGrid(fig, 111, # similar to subplot(111)
nrows_ncols = (2, 5), # creates 2x2 grid of axes
axes_pad=0.1, # pad between axes in inch.
)
"""
num_rows = 2
num_cols = 5
fig = plt.figure()
gs = gridspec.GridSpec(num_rows, num_cols, wspace=0.0)
ax = [plt.subplot(gs[i]) for i in range(num_rows*num_cols)]
gs.update(hspace=0)
#gs.tight_layout(fig, h_pad=0,w_pad=0)
for i,im in enumerate(images):
ax[i].imshow(im)
ax[i].axis('off')
#ax_grid[i/num_cols,i-(i/num_cols)*num_cols].imshow(im) # The AxesGrid object work as a list of axes.
#ax_grid[i/num_cols,i-(i/num_cols)*num_cols].axis('off')
"""
all_axes = fig.get_axes()
for ax in all_axes:
for sp in ax.spines.values():
sp.set_visible(False)
if ax.is_first_row():
ax.spines['top'].set_visible(True)
if ax.is_last_row():
ax.spines['bottom'].set_visible(True)
if ax.is_first_col():
ax.spines['left'].set_visible(True)
if ax.is_last_col():
ax.spines['right'].set_visible(True)
"""
plt.show()
Also does anyone know how to make each subplot bigger?
For me a combination of aspect="auto" and subplots_adjust worked. Also I always try to make the subplots quadratic. For the individual subplot size figsize can be adjusted.
fig, axes = plt.subplots(nrows=max_rows, ncols=max_cols, figsize=(20,20))
for idx, image in enumerate(images):
row = idx // max_cols
col = idx % max_cols
axes[row, col].axis("off")
axes[row, col].imshow(image, cmap="gray", aspect="auto")
plt.subplots_adjust(wspace=.05, hspace=.05)
plt.show()