I want to generate colorplot subplots based on a numpy array's length which I call dets. I want to use the array length to determine the right number of columns and rows for the subplots. If square, plot a square matrix of subplots, if not square, add another row. For starters, I have written some code to check if the array's length would create a square matrix of subplots with the following:
data_f = np.random.rand(len(dets),2,5)
dets = np.arange(-5,-0.75,0.25)
x = np.array([1,5,6,3,8,9,2,3,10,12,3])
v = np.linspace(0,10,len(x))
square = np.sqrt(len(dets))
check_square = len(dets)%square
non_square = 1
print(len(data_f))
if check_square == 0:
nrows = int(np.sqrt(len(dets)))
ncols = int(np.sqrt(len(dets)))
else:
nrows = int(np.sqrt(len(dets)))+non_square
ncols = int(np.sqrt(len(dets)))
fig, ax = plt.subplots(nrows, ncols, sharex='col', sharey='row')
for i in range(nrows):
for j in range(ncols):
if i==0:
im = ax[i,j].imshow(data_f[j],extent=(x.min(), x.max(), v.min(), v.max()),origin='lower',aspect='auto')
else:
im = ax[i,j].imshow(data_f[j+ncols*i],extent=(x.min(), x.max(), v.min(), v.max()),origin='lower',aspect='auto')
The output plot:
This plots 17 plots but the resulting plots I cannot adjust because of the error
This plots everything I want, except it always smushes the plots together in a weird way because of the following error:
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
~\AppData\Local\Temp\1/ipykernel_4560/3817292743.py in <module>
6 im = ax[i,j].imshow(data_f[j],extent=(x.min(), x.max(), v.min(), v.max()),origin='lower',aspect='auto')
7 else:
----> 8 im = ax[i,j].imshow(data_f[j+ncols*i],extent=(x.min(), x.max(), v.min(), v.max()),origin='lower',aspect='auto')
9
IndexError: index 17 is out of bounds for axis 0 with size 17
It is because you have a total of 20 axes, and when you loop through ncols and nrows, you will get 20 iterations. But len(data_f) is only 17.
at the start of your iteration, add
if(j + ncols*i) == len(data_f):
break
I did this and it stopped the error
Related
I would like my sybplots to be generated in 2x columns and 5x rows.
I've also tried adding ncols=2, nrows=5 to the code. didn't work.
And when I change the subplots to plt.subplots(5,2) instead of plt.subplots(10,1) it says (see added picture of code+error message):
AttributeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_9844/709244097.py in
13
14 for ax, afstand, tid in zip(ax, afstande, tider):
---> 15 ax.plot(tid, afstand)
16 ax.set_title("x(t)", fontsize=12)
17 ax.set_xlabel("tid (s)", fontsize=12)
AttributeError: 'numpy.ndarray' object has no attribute 'plot'
My code:
from scipy.optimize import fmin
a = -75.64766759
b = 68.02691163
f = lambda x: a * x + b
afstand1, afstand2, afstand3, afstand4, afstand5, afstand6, afstand7, afstand8, afstand9, afstand10 = f(U1), f(U2), f(U3), f(U4), f(U5),f(U6), f(U7), f(U8), f(U9), f(U10)
afstande = [afstand1, afstand2, afstand3, afstand4, afstand5, afstand6, afstand7, afstand8, afstand9, afstand10]
tider = [tid1, tid2, tid3, tid4, tid5, tid6, tid7, tid8, tid9, tid10]
fig, ax = plt.subplots(10,1, figsize=(7,25))
plt.subplots_adjust(hspace=0.55)
#loop
for ax, afstand, tid in zip(ax, afstande, tider):
ax.plot(tid, afstand)
ax.set_title("x(t)", fontsize=12)
ax.set_xlabel("tid (s)", fontsize=12)
ax.set_ylabel("Position", fontsize=12)
enter image description here
First of all, you're using the same variable name for the array of axis and in the loop, you should change that. Subplot-axes are stored in numpy arrays. If you only have 1 row, then looping over the array gives you the elements, but in a x*y pattern of subplots, you loop over a two-dimensional array of axis, which yields the rows. You can solve that by using .flat to get a one-dimensional view.
fig, axs = plt.subplots(ncols=5, nrows=2)
for ax in axs.flat:
ax.plot(...)
I am learning horse-colic dataset.
thanks to #Vaishali #Ultra TLC #Tom 's help, the data is imported.
p_data = 'https://raw.githubusercontent.com/MachineIntellect/dataset.ml/master/horse_colic.csv'
df = pd.read_csv(p_data)
df = df.replace("?", np.NaN)
df = df.astype(np.float)
to get the number of cols and rows to plot, this piece of code works well too
%matplotlib inline
n_col = 4
n_row = int(math.ceil(df.shape[1] * 1.0/n_col))
when i try to plot a hist
fig, axes = plt.subplots(n_row, n_col, figsize=(15, 30))
plt.tight_layout()
for i, col in enumerate(df.columns):
pos_i = i / n_col
pos_j = i % n_col
df.groupby("cp_data")[col].plot.hist(title=col, alpha=0.5, ax=axes[pos_i, pos_j]);
error shows up
IndexError Traceback (most recent call last)
<ipython-input-1-e6f18b850dfa> in <module>()
17 pos_i = i / n_col
18 pos_j = i % n_col
---> 19 df.groupby("cp_data")[col].plot.hist(title=col, alpha=0.5, ax=axes[pos_i, pos_j]);
20
21
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
why plot a hist would cause IndexError?
It seems that something wrong happens somewhere at plot.hist(), how to figure it out?
I have the following:
import matplotlib.pyplot as plt
fig = plt.figure()
for i in range(10):
ax = fig.add_subplot(551 + i)
ax.plot([1,2,3,4,5], [10,5,10,5,10], 'r-')
I was imagining that the 55 means that it is creating a grid that is 5 subplots wide and 5 subplots deep - so can cater for 25 subplots?
The for loop will just iterate 10 times - so I thought (obviously wrongly) that 25 possible plots would accomodate those iterations ok but I get the following:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-118-5775a5ea6c46> in <module>()
10
11 for i in range(10):
---> 12 ax = fig.add_subplot(551 + i)
13 ax.plot([1,2,3,4,5], [10,5,10,5,10], 'r-')
14
/home/blah/anaconda/lib/python2.7/site-packages/matplotlib/figure.pyc in add_subplot(self, *args, **kwargs)
1003 self._axstack.remove(ax)
1004
-> 1005 a = subplot_class_factory(projection_class)(self, *args, **kwargs)
1006
1007 self._axstack.add(key, a)
/home/blah/anaconda/lib/python2.7/site-packages/matplotlib/axes/_subplots.pyc in __init__(self, fig, *args, **kwargs)
62 raise ValueError(
63 "num must be 1 <= num <= {maxn}, not {num}".format(
---> 64 maxn=rows*cols, num=num))
65 self._subplotspec = GridSpec(rows, cols)[int(num) - 1]
66 # num - 1 for converting from MATLAB to python indexing
ValueError: num must be 1 <= num <= 30, not 0
In the convience shorthand notation, the 55 does mean there are 5 rows and 5 columns. However, the shorthand notation only works for single-digit integers (i.e. for nrows, ncols and plot_number all less than 10).
You can expand it to full notation (i.e. use commas: add_subplot(nrows, ncols, plot_number)) and then all will work fine for you:
for i in range(10):
ax = fig.add_subplot(5, 5, 1 + i)
ax.plot([1,2,3,4,5], [10,5,10,5,10], 'r-')
From the docs for plt.subplot (which uses the same args as fig.add_subplot) :
Typical call signature:
subplot(nrows, ncols, plot_number)
Where nrows and ncols are used to notionally split the figure into nrows * ncols sub-axes, and
plot_number is used to identify the particular subplot that this
function is to create within the notional grid. plot_number starts at
1, increments across rows first and has a maximum of nrows * ncols.
In the case when nrows, ncols and plot_number are all less than 10, a convenience exists, such that the a 3 digit number can be given
instead, where the hundreds represent nrows, the tens represent ncols
and the units represent plot_number.
Although tom answered your question, in this sort of situation you should be using fig, axs = plt.subplots(n, m). This will create a new figure with the n rows and m columns of subplots. fig is the figure created. axs is a 2D numpy array where each element in the array is the subplot in the corresponding location in the figure. So the top-right element axs is the top-right subplot in the figure. You can access the subplots through normal indexing, or loop over them.
So in your case you can do
import matplotlib.pyplot as plt
# axs is a 5x5 numpy array of axes objects
fig, axs = plt.subplots(5, 5)
# "ravel" flattens the numpy array without making a copy
for ax in axs.ravel():
ax.plot([1,2,3,4,5], [10,5,10,5,10], 'r-')
I have a three-dimensional array.
The first dimension has 4 elements.
The second dimension has 10 elements.
The third dimension has 5 elements.
I want to plot the contents of this array as follows.
Each element of the first dimension gets its own graph (four graphs on the page)
The values of the second dimension correspond to the y values of the graphs. (there are 10 lines on each graph)
The values of the third dimension correspond to the x values of the graphs (each of the 10 lines has 5 x values)
I'm pretty new to python, and even newer to graphing.
I figured out how to correctly load my array with the data...and I'm not even trying to get the 'four graphs on one page' aspect working.
For now I just want one graph to work correctly.
Here's what I have so far (once my array is set up, and I've correctly loaded my arrays. Right now the graph shows up, but it's blank, and the x-axis includes negative values. None of my data is negative)
for n in range(1):
for m in range(10):
for o in range(5):
plt.plot(quadnumcounts[n][m][o])
plt.xlabel("Trials")
plt.ylabel("Frequency")
plt.show()
Any help would be really appreciated!
Edit. Further clarification. Let's say my array is loaded as follows:
myarray[0][1][0] = 22
myarray[0][1][1] = 10
myarray[0][1][2] = 15
myarray[0][1][3] = 25
myarray[0][1][4] = 13
I want there to be a line, with the y values 22, 10, 15, 25, 13, and the x values 1, 2, 3, 4, 5 (since it's 0 indexed, I can just +1 before printing the label)
Then, let's say I have
myarray[0][2][0] = 10
myarray[0][2][1] = 17
myarray[0][2][2] = 9
myarray[0][2][3] = 12
myarray[0][2][4] = 3
I want that to be another line, following the same rules as the first.
Here's how to make the 4 plots with 10 lines in each.
import matplotlib.pyplot as plt
for i, fig_data in enumerate(quadnumcounts):
# Set current figure to the i'th subplot in the 2x2 grid
plt.subplot(2, 2, i + 1)
# Set axis labels for current figure
plt.xlabel('Trials')
plt.ylabel('Frequency')
for line_data in fig_data:
# Plot a single line
xs = [i + 1 for i in range(len(line_data))]
ys = line_data
plt.plot(xs, ys)
# Now that we have created all plots, show the result
plt.show()
Here is the example of creating subplots of your data. You have not provided the dataset so I used x to be an angle from 0 to 360 degrees and the y to be the trigonemetric functions of x (sine and cosine).
Code example:
import numpy as np
import pylab as plt
x = np.arange(0, 361) # 0 to 360 degrees
y = []
y.append(1*np.sin(x*np.pi/180.0))
y.append(2*np.sin(x*np.pi/180.0))
y.append(1*np.cos(x*np.pi/180.0))
y.append(2*np.cos(x*np.pi/180.0))
z = [[x, y[0]], [x, y[1]], [x, y[2]], [x, y[3]]] # 3-dimensional array
# plot graphs
for count, (x_data, y_data) in enumerate(z):
plt.subplot(2, 2, count + 1)
plt.plot(x_data, y_data)
plt.xlabel('Angle')
plt.ylabel('Amplitude')
plt.grid(True)
plt.show()
Output:
UPDATE:
Using the sample date you provided in your update, you could proceed as follows:
import numpy as np
import pylab as plt
y1 = (10, 17, 9, 12, 3)
y2 = (22, 10, 15, 25, 13)
y3 = tuple(reversed(y1)) # generated for explanation
y4 = tuple(reversed(y2)) # generated for explanation
mydata = [y1, y2, y3, y4]
# plot graphs
for count, y_data in enumerate(mydata):
x_data = range(1, len(y_data) + 1)
print x_data
print y_data
plt.subplot(2, 2, count + 1)
plt.plot(x_data, y_data, '-*')
plt.xlabel('Trials')
plt.ylabel('Frequency')
plt.grid(True)
plt.show()
Note that the dimensions are slightly different from yours. Here they are such that mydata[0][0] == 10, mydata[1][3] == 25 etc. The output is show below:
I have 6 lists and I want to create scatterplots for all possible combinations. This means that I want to create n(n-1)/2 combinations, so 15 plots. I have done this correctly based on the following
script.
for i in d:
for j in d:
if(j>i):
plt.cla() # Clear axis
plt.clf() # Clear figure
correlation_coefficient = str(np.corrcoef(d[i], d[j])[0][1])
plt.scatter(d[i],d[j])
plt.xlabel(names[i])
plt.ylabel(names[j])
plt.title('Correlation Coefficient: '+correlation_coefficient)
plt.grid()
plt.savefig(names[i]+"_"+names[j]+".png")
I want to save all these plots in one figure using subplot, where the first row will have the combinations (0,1) (0,2) (0,3) (0,4) (0,5) the second row (1,2) (1,3) (1,4) (1,5) the third row (2,3) (2,4) (2,5) etc.
So the final outcome will be a figure containing subplots in triangular form.
Update:
If I use subplots (code below) I was able to get somehow the result, but it is not optimal as I create a 6x6 frame whereas you can do it with 5x5.
fig = plt.figure()
cnt = 0
# Create scatterplots for all pairs
for i in d:
for j in d:
if(i>=j):
cnt=cnt+1
if(j>i):
cnt += 1
fig.add_subplot(6,6,cnt) #top left
correlation_coefficient = str(np.corrcoef(d[i], d[j])[0][1])
plt.scatter(np.log(d[i]),np.log(d[j]))
fig.savefig('test.png')
With gridspec:
from matplotlib import pyplot as plt
fig = plt.figure()
data = [(1,2,3),(8,2,3),(0,5,2),(4,7,1),(9,5,2),(8,8,8)]
plotz = len(data)
for i in range(plotz-1):
for j in range(plotz):
if(j>i) :
print(i,j)
ax = plt.subplot2grid((plotz-1, plotz-1), (i,j-1))
ax.xaxis.set_ticklabels([])
ax.yaxis.set_ticklabels([])
plt.scatter(data[i],data[j]) # might be nice with shared axis limits
fig.show()
With add_subplot, you've hit an oddity inherited from MATLAB, which 1-indexes the subplot count. (Also you have some counting errors.) Here's an example that just keeps track of the various indices:
from matplotlib import pyplot as plt
fig = plt.figure()
count = 0
data = [(1,2,3),(8,2,3),(0,5,2),(4,7,1),(9,5,2),(8,8,8)]
plotz = len(data)
for i in range(plotz-1):
for j in range(plotz):
if(j>i):
print(count, i,j, count -i)
ax = fig.add_subplot(plotz-1, plotz-1, count-i)
ax.xaxis.set_ticklabels([])
ax.yaxis.set_ticklabels([])
plt.text(.15, .5,'i %d, j %d, c %d'%(i,j,count))
count += 1
fig.show()
N.b.: the error from doing the obvious (your original code with add_subplot(5,5,cnt)) was a good hint:
...User/lib/python2.7/site-packages/matplotlib/axes.pyc in
init(self, fig, *args, **kwargs)
9249 self._subplotspec = GridSpec(rows,
cols)[num[0] - 1:num1]
9250 else:
-> 9251 self._subplotspec = GridSpec(rows, cols)[int(num) - 1]
9252 # num - 1 for converting from MATLAB to
python indexing