I'm getting the blank plot by using the below code and data file. Could you please let me know what's wrong with data file or the code?
import numpy as np
import matplotlib.pyplot as plt
data = np.genfromtxt('file1.txt', delimiter=' ')
lats = data[:,0]
lons = data[:,1] values = data[:,2]
lat_uniq, lat_idx = np.unique(lats, return_inverse=True)
lon_uniq, lon_idx = np.unique(lons, return_inverse=True)
xre, yre = np.meshgrid(lon_uniq, lat_uniq)
zre = np.full(xre.shape, np.nan)
zre[lat_idx, lon_idx] = values
print(zre)
fig, (ax1) = plt.subplots(1,1, figsize = (10, 5))
cp1 = ax1.contourf(xre, yre, zre, levels=4)
plt.colorbar(cp1, ax=ax1)
ax1.set_title("data are not interpolated") plt.show()
test.txt file --
1 2 3
4 5 6
7 8 9
10 11 12
Your program has no problem
There were none values in your matrix, in which case the graph will not be drawn.
It makes no sense to have null values in a matrix and try to draw those points.
By changing its values, the 'contourf' command can fit the values of X, Y, and Z, and the graph is drawn.
See this :
import numpy as np
import matplotlib.pyplot as plt
data = np.genfromtxt('test.txt', delimiter=' ')
lats = data[:, 0]
lons = data[:, 1]
values = data[:, 2]
lat_uniq, lat_idx = np.unique(lats, return_inverse=True)
lon_uniq, lon_idx = np.unique(lons, return_inverse=True)
xre, yre = np.meshgrid(lon_uniq, lat_uniq)
# zre = np.full(xre.shape, np.nan)
zre = np.full(xre.shape, 0)
zre[lat_idx, lon_idx] = values
print(zre)
fig, (ax1) = plt.subplots(1, 1, figsize=(10, 5))
cp1 = ax1.contourf(xre, yre, zre, levels=4)
plt.colorbar(cp1, ax=ax1)
ax1.set_title("data are not interpolated")
plt.show()
Output:
Related
How do we show an equation in the legend of a pyplot plot?
Sample code below:
fig = plt.figure(figsize=(5, 3), dpi=my_dpi)
ax = fig.add_subplot(111)
a = 2.0
b = 3.0
xdata = np.arange(6)
ydata = a*np.power(xdata,b)
# I want the b variable in the equation below to be a subscript.
label = '${0:.2f} x^{{0:.2f}}$'.format(a,b)
plt.plot(xdata,ydata, alpha = 0.5, label = label)
plt.legend()
plt.show()
One possible solution: first format your float to strings, than put the strings together:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5, 3))
ax = fig.add_subplot(111)
a = 2.0
b = 3.0
xdata = np.arange(6)
ydata = a*np.power(xdata,b)
f2str = '{:.2f}'
label = '$%s x^{%s}$' % tuple(f2str.format(t) for t in [a, b])
plt.plot(xdata,ydata, alpha = 0.5, label = label)
plt.legend()
plt.show()
I want to make a plot from a data file with matplotlib.pyplot and I want every marker (triangle) to have an orientation which has been given in the input file.
The input file :
x y angle
1 1 10
1.2 1.2 20
1.3 1.3 30
and this is my code:
import numpy as np
import matplotlib.pyplot as plt
infile = open ('traj_marker.txt')
#for s in xrange(8):
x, y = [], []
m = []
for i in xrange(3):
data = infile.readline()
raw = data.split()
x.append(float(raw[0]))
y.append(float(raw[1]))
m.append(float(raw[2]))
xnp = np.array(x)
ynp = np.array(y)
mnp = np.array(m)
fig, ax = plt.subplots()
ax.scatter(xnp, ynp, 100, marker = (3,0,mnp))
plt.xticks (range(1,3))
plt.yticks (range(1,3))
plt.grid()
fig.savefig ('trj.png')
infile.close()
But the presence of array mnp in marker produces error.
How can I solve this?
Matplotlib doesn't like the marker argument passed as a list, so run it in the following manner ...
N = 20
xnp = np.random.rand(N)
ynp = np.random.rand(N)
mnp = np.random.randint(0, 180, N)
fig, ax = plt.subplots()
for x, y, m in zip(xnp, ynp, mnp):
ax.scatter(x, y, 100, marker = (3,0,m))
plt.show()
Just in case you are not aware, you can use quiver to plot 2D fields:
x = [1, 1.2, 1.3]
y = [1, 1.2, 1.3]
angle = [10, 20, 30]
plt.quiver(x, y, np.cos(np.radians(angle)), np.sin(np.radians(angle)))
This is my code :
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
with open("TestGraph.txt") as f:
data = f.read()
data = data.split('\n')
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
x = [row.split(' ')[0] for row in data]
y = [row.split(' ')[1] for row in data]
z = [row.split(' ')[2] for row in data]
ax.plot_wireframe(x, y,z)
plt.show()
TestGraph.txt is
1 2 3
3 4 5
5 6 7
7 8 9
9 1 8
When I print out x , y , z they are all the right values. I don't understand what the error means.
Your x, y and z variables are lists of strings (S32). The plot_wireframe expects float (float64). Here's a simpler solution. You can use pandas too.
import numpy as np
import matplotlib.pyplot as plt
f = r"TestGraph.txt"
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
data = np.loadtxt(f)
x = data[:, 0]
y = data[:, 1]
z = data[:, 2]
ax.plot_wireframe(x, y, z)
plt.show()
I have an GridSpec defined layout with to subgrids, one is supposed to include a colorbar
import pylab as plt
import numpy as np
gs_outer = plt.GridSpec(1, 2, width_ratios=(10, 1))
gs_inner = plt.matplotlib.gridspec.GridSpecFromSubplotSpec(2, 3, gs_outer[0])
ax = []
for i in xrange(6):
ax.append(plt.subplot(gs_inner[i]))
plt.setp(ax[i].get_xticklabels(), visible=False)
plt.setp(ax[i].get_yticklabels(), visible=False)
ax.append(plt.subplot(gs_outer[1]))
plt.show()
I'd now like to get for the left part a row-wise labeling like this:
I tried to add another GridSpec into the GridSpec, but that did not work out:
import pylab as plt
import numpy as np
fig = plt.figure()
gs_outer = plt.GridSpec(1, 2, width_ratios=(10, 1))
gs_medium = plt.matplotlib.gridspec.GridSpecFromSubplotSpec(3, 1, gs_outer[0])
ax_title0 = plt.subplot(gs_medium[0])
ax_title0.set_title('Test!')
gs_row1 = plt.matplotlib.gridspec.GridSpecFromSubplotSpec(1, 3, gs_medium[0])
ax00 = plt.subplot(gs_row1[0]) # toggle this line to see the effect
plt.show()
Adding the ax00 = plt.subplot... line seems to erase the previously created axis
Following CT Zhu comment I came up with the following answer (I don't really like it, but it seems to work)
import pylab as plt
import numpy as np
fig = plt.figure()
rows = 2
cols = 3
row_fraction = 9
row_size = row_fraction / float(rows)
gs_outer = plt.GridSpec(1,2, width_ratios=(9,1))
gs_plots= plt.matplotlib.gridspec.GridSpecFromSubplotSpec(rows * 2, cols, subplot_spec=gs_outer[0], height_ratios = rows * [1, row_size])
# Create title_axes
title_ax = []
for ta in xrange(rows):
row_index = (ta) * 2
title_ax.append(plt.subplot(gs_plots[row_index, :]))
# Create Data axes
ax = []
for row in xrange(rows):
row_index = (row + 1) * 2 -1
for col in xrange(cols):
try:
ax.append(plt.subplot(gs_plots[row_index, col], sharex=ax[0], sharey=ax[0]))
except IndexError:
if row == 0 and col == 0:
ax.append(plt.subplot(gs_plots[row_index, col]))
else:
raise IndexError
# Delete Boxes and Markers from title axes
for ta in title_ax:
ta._frameon = False
ta.xaxis.set_visible(False)
ta.yaxis.set_visible(False)
# Add labels to title axes:
for ta, label in zip(title_ax, ['Row 1', 'Row 2']):
plt.sca(ta)
plt.text(
0.5, 0.5, label, horizontalalignment='center', verticalalignment='center')
# Add common colorbar
gs_cb = plt.matplotlib.gridspec.GridSpecFromSubplotSpec(
1, 1, subplot_spec=gs_outer[1])
ax.append(plt.subplot(gs_cb[:, :]))
Of course labeling and ticklabels could be improved. But how to achive that is likely already explained on SO.
Let's define an example grid pltgrid:
pltgrid = gridspec.GridSpec(ncols=3, nrows=2,
width_ratios=[1]*3, wspace=0.3,
hspace=0.6, height_ratios=[1]*2)
Before your for loop, you can define a list ax using map:
num=list(range(7))
ax=list(map(lambda x : 'ax'+str(x), num))
You may have a list plotnames containing the names. As an example, I'll plot a normal distribution Q-Q plot for each i in the for loop:
for i in xrange(6):
ax[i]=fig.add.subplot(pltgrid[i])
res = stats.probplot(x, dist="norm", plot=ax[i])
# set title for subplot using existing 'plotnames' list
ax[i].set_title(plotnames[i])
# display subplot
ax[i]
I am trying to create a 10x10 grid using either imshow or matshow in Matplotlib. The function below takes a numpy array as input, and plots the grid. However, I'd like to have values from the array also displayed inside the cells defined by the grid. So far I could not find a proper way to do it. I can use plt.text to place things over the grid, but this requires coordinates of each cell, totally inconvenient. Is there a better way to do what I am trying to accomplish?
Thanks!
NOTE: The code below does not take the values from the array yet, I was just playing with plt.text.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
board = np.zeros((10, 10))
def visBoard(board):
cmap = colors.ListedColormap(['white', 'red'])
bounds=[0,0.5,1]
norm = colors.BoundaryNorm(bounds, cmap.N)
plt.figure(figsize=(4,4))
plt.matshow(board, cmap=cmap, norm=norm, interpolation='none', vmin=0, vmax=1)
plt.xticks(np.arange(0.5,10.5), [])
plt.yticks(np.arange(0.5,10.5), [])
plt.text(-0.1, 0.2, 'x')
plt.text(0.9, 0.2, 'o')
plt.text(1.9, 0.2, 'x')
plt.grid()
visBoard(board)
Output:
Can you do something like:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
min_val, max_val = 0, 10
ind_array = np.arange(min_val + 0.5, max_val + 0.5, 1.0)
x, y = np.meshgrid(ind_array, ind_array)
for i, (x_val, y_val) in enumerate(zip(x.flatten(), y.flatten())):
c = 'x' if i%2 else 'o'
ax.text(x_val, y_val, c, va='center', ha='center')
#alternatively, you could do something like
#for x_val, y_val in zip(x.flatten(), y.flatten()):
# c = 'x' if (x_val + y_val)%2 else 'o'
ax.set_xlim(min_val, max_val)
ax.set_ylim(min_val, max_val)
ax.set_xticks(np.arange(max_val))
ax.set_yticks(np.arange(max_val))
ax.grid()
Edit:
Here is an updated example with an imshow background.
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
min_val, max_val, diff = 0., 10., 1.
#imshow portion
N_points = (max_val - min_val) / diff
imshow_data = np.random.rand(N_points, N_points)
ax.imshow(imshow_data, interpolation='nearest')
#text portion
ind_array = np.arange(min_val, max_val, diff)
x, y = np.meshgrid(ind_array, ind_array)
for x_val, y_val in zip(x.flatten(), y.flatten()):
c = 'x' if (x_val + y_val)%2 else 'o'
ax.text(x_val, y_val, c, va='center', ha='center')
#set tick marks for grid
ax.set_xticks(np.arange(min_val-diff/2, max_val-diff/2))
ax.set_yticks(np.arange(min_val-diff/2, max_val-diff/2))
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_xlim(min_val-diff/2, max_val-diff/2)
ax.set_ylim(min_val-diff/2, max_val-diff/2)
ax.grid()
plt.show()
For your graph you should should try with pyplot.table:
import matplotlib.pyplot as plt
import numpy as np
board = np.zeros((10, 10))
board[0,0] = 1
board[0,1] = -1
board[0,2] = 1
def visBoard(board):
data = np.empty(board.shape,dtype=np.str)
data[:,:] = ' '
data[board==1.0] = 'X'
data[board==-1.0] = 'O'
plt.axis('off')
size = np.ones(board.shape[0])/board.shape[0]
plt.table(cellText=data,loc='center',colWidths=size,cellLoc='center',bbox=[0,0,1,1])
plt.show()
visBoard(board)
Some elaboration on the code of #wflynny making it into a function that takes any matrix no matter what size and plots its values.
import numpy as np
import matplotlib.pyplot as plt
cols = np.random.randint(low=1,high=30)
rows = np.random.randint(low=1,high=30)
X = np.random.rand(rows,cols)
def plotMat(X):
fig, ax = plt.subplots()
#imshow portion
ax.imshow(X, interpolation='nearest')
#text portion
diff = 1.
min_val = 0.
rows = X.shape[0]
cols = X.shape[1]
col_array = np.arange(min_val, cols, diff)
row_array = np.arange(min_val, rows, diff)
x, y = np.meshgrid(col_array, row_array)
for col_val, row_val in zip(x.flatten(), y.flatten()):
c = '+' if X[row_val.astype(int),col_val.astype(int)] < 0.5 else '-'
ax.text(col_val, row_val, c, va='center', ha='center')
#set tick marks for grid
ax.set_xticks(np.arange(min_val-diff/2, cols-diff/2))
ax.set_yticks(np.arange(min_val-diff/2, rows-diff/2))
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_xlim(min_val-diff/2, cols-diff/2)
ax.set_ylim(min_val-diff/2, rows-diff/2)
ax.grid()
plt.show()
plotMat(X)