I have a series of 9 subplots in a 3x3 grid, each subplot with a title.
I want to add a title for each row. To do so I thought about using suptitle.
The problem is if I use 3 suptitles they seems to be overwritten and only the last one seems to be shown.
Here is my basic code:
fig, axes = plt.subplots(3,3,sharex='col', sharey='row')
for j in range(9):
axes.flat[j].set_title('plot '+str(j))
plt1 = fig.suptitle("row 1",x=0.6,y=1.8,fontsize=18)
plt2 = fig.suptitle("row 2",x=0.6,y=1.2,fontsize=18)
plt3 = fig.suptitle("row 3",x=0.6,y=0.7,fontsize=18)
fig.subplots_adjust(right=1.1,top=1.6)
You can tinker with the titles and labels. Check the following example adapted from your code:
import matplotlib.pyplot as plt
fig, axes = plt.subplots(3,3,sharex='col', sharey='row')
counter = 0
for j in range(9):
if j in [0,3,6]:
axes.flat[j].set_ylabel('Row '+str(counter), rotation=0, size='large',labelpad=40)
axes.flat[j].set_title('plot '+str(j))
counter = counter + 1
if j in [0,1,2]:
axes.flat[j].set_title('Column '+str(j)+'\n\nplot '+str(j))
else:
axes.flat[j].set_title('plot '+str(j))
plt.show()
, which results in:
Related
I have a text file that contain 2048 rows and 256 columns, i want to plot only 10 columns of data in an subplot,
I tried
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
data=np.loadtxt("input_data.txt")
data=data[:,0:10]
print(data.shape)
nrows=5
ncols=10
fig, axs = plt.subplots(nrows,ncols, figsize=(13,10))
count = 0
for i in range(ncols):
for j in range(nrows):
axs[i,j].plot(data[count])
count += 1
print(count)
plt.show()
But it doesnot plot the each column values, I hope experts may help me.Thanks.
I used random numbers to reproduce your problem.
data=np.random.randint(0,1,size = (2048,256))
data=data[:,0:10]
print(np.shape(data))
nrows=2
ncols=5
fig, axs = plt.subplots(nrows,ncols, figsize=(13,10))
count = 0
for i in range(nrows):
for j in range(ncols):
print(count)
axs[i,j].plot(data[:,count])
count += 1
Here is your plot.
if you put real data you will see some variation in each subplot.
This question already has answers here:
How to plot in multiple subplots
(12 answers)
Closed 1 year ago.
I am using the Lombscargle function to output the power spectrum for a signal I pass as input, I am able to get the plots one after another but the task at hand is to plot these graphs using subplots in a way that there are 5 rows, 4 cols.
An example for signal would be:
signal = [ '254.24', '254.32', '254.4', '254.84', '254.24', '254.28', '254.84', '253.56', '253.76', '253.32', '253.88', '253.72', '253.92', '251.56', '253.04', '244.72', '243.84', '246.08', '245.84', '249.0', '250.08', '248.2', '253.12', '253.2', '253.48', '253.88', '253.12', '253.4', '253.4']
from scipy.signal import lombscargle
def LSP_scipy(signal):
start_ang_freq = 2 * np.pi * (60/60)
end_ang_freq = 2 * np.pi * (240/60)
SAMPLES = 5000
SAMPLE_SPACING = 1/15
t = np.linspace(0,len(signal)*SAMPLE_SPACING,len(signal))
period_freq = np.linspace(start_ang_freq,end_ang_freq,SAMPLES)
modified_signal_axis = []
modified_time_axis = []
for count,value in enumerate(signal):
if value != 'None':
modified_signal_axis.append(float(value))
modified_time_axis.append(t[count])
prog = lombscargle(modified_time_axis, modified_signal_axis, period_freq, normalize=False, precenter = True)
fig, axes = plt.subplots()
ax.plot(period_freq,prog)
How do I plot these graphs in a matrix format?
Trying loop approach,
See inline comments to add and flatten the subplots.
This is an implementation of flattening the axes array from this answer of the duplicate.
from scipy.signal import lombscargle
from matplotlib.ticker import FormatStrFormatter
import numpy as np
import matplotlib.pyplot as plt
def LSP_scipy(signal):
start_ang_freq = 2 * np.pi * (60/60)
end_ang_freq = 2 * np.pi * (240/60)
SAMPLES = 5000
SAMPLE_SPACING = 1/15
t = np.linspace(0, len(signal)*SAMPLE_SPACING, len(signal))
period_freq = np.linspace(start_ang_freq, end_ang_freq, SAMPLES)
modified_signal_axis = []
modified_time_axis = []
# create the figure and subplots
fig, axes = plt.subplots(5, 6, figsize=(20, 9), sharex=False, sharey=False)
# flatten the array
axes = axes.ravel()
for count, value in enumerate(signal):
if value != 'None':
modified_signal_axis.append(float(value))
modified_time_axis.append(t[count])
prog = lombscargle(modified_time_axis, modified_signal_axis, period_freq, normalize=False, precenter=True)
# plot
axes[count].plot(period_freq, prog)
# format the axes
axes[count].set(title=value)
# some plot have an exponential offset on the yaxis, this turns it off
axes[count].ticklabel_format(useOffset=False)
# some yaxis values are long floats, this formats them to 3 decimal places
axes[count].yaxis.set_major_formatter(FormatStrFormatter('%.3f'))
# format the figure
fig.tight_layout()
signal = [ '254.24', '254.32', '254.4', '254.84', '254.24', '254.28', '254.84', '253.56', '253.76', '253.32', '253.88', '253.72', '253.92', '251.56', '253.04', '244.72', '243.84', '246.08', '245.84', '249.0', '250.08', '248.2', '253.12', '253.2', '253.48', '253.88', '253.12', '253.4', '253.4']
LSP_scipy(signal[:20]) # as per comment, only first 20
You can use for loop and iterate over subplots. A very simple example is shown below.The subplots method creates the figure along with the subplots and store in the ax array.
import matplotlib.pyplot as plt
x = np.linspace(0, 10)
y = range(10)
fig, ax = plt.subplots(nrows=2, ncols=2)
for row in ax:
for col in row:
col.plot(x, y)
plt.show()
# or you can also do
for in range(2): # row=0, col=0
for j in range(2): # row=0, col=1
ax[i, j].plot(x,y) # row=1, col=0
# row=1, col=1
Then one idea is to take the signals into an array of shape=(20,1), where each row corresponds to signal amplitude or some other measurable quantity. Then you could do as below (check the output keeping only the lines till plt.text you will get the idea).
for i in range(1, 21):
plt.subplot(5, 4, i)
plt.text(0.5, 0.5, str((5, 4, i)),
fontsize=18, ha='center')
# Call the function here...get the value of period_freq and prog
period_freq,prog = LSP_scipy(signal[i])
plt.plot(period_freq, prog)
I want to create a python programm that is able to plot multiple graphs into one PDF file, however the number of subplots is variable. I did this already with one plot per page. However, since i got someteimes arround 100 plots that makes a lot of scrolling and is not really clearly shown. Therefore I would like to get like 5X4 subpltots per page.
I wrote code for that alreaedy, the whole code is long and since im very new to pyhton it looks terrible to someone who knows what to do, however the ploting part looks like this:
rows = (len(tags))/5
fig = plt.figure()
count = 0
for keyInTags in tags:
count = count + 1
ax = fig.add_subplot(int(rows), 5, count)
ax.set_title("cell" + keyInTags)
ax.plot(x, y_green, color='k')
ax.plot(x, y_red, color='k')
plt.subplots_adjust(hspace=0.5, wspace=0.3)
pdf.savefig(fig)
The idea is that i get an PDF with all "cells" (its for biological research) ploted. The code I wrote is working fine so far, however if I got more than 4 rows of subplots I would like to do a "pageprake". In some cases i got over 21 rows on one page, that makes it impossible to see anything.
So, is there a solution to, for example, tell Python to do a page break after 4 rows? In the case with 21 rows id like to have 6 pages with nice visible plots. Or is it done by doing 5x4 plots and then iterating somehow over the file?
I would be really happy if someone could help a little or give a hint. Im sitting here since 4 hours, not finding a solution.
A. Loop over pages
You could find out how many pages you need (npages) and create a new figure per page.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
tags = ["".join(np.random.choice(list("ABCDEFG123"), size=5)) for _ in range(53)]
N = len(tags) # number of subplots
nrows = 5 # number of rows per page
ncols = 4 # number of columns per page
# calculate number of pages needed
npages = N // (nrows*ncols)
if N % (nrows*ncols) > 0:
npages += 1
pdf = PdfPages('out2.pdf')
for page in range(npages):
fig = plt.figure(figsize=(8,11))
for i in range(min(nrows*ncols, N-page*(nrows*ncols))):
# Your plot here
count = page*ncols*nrows+i
ax = fig.add_subplot(nrows, ncols, i+1)
ax.set_title(f"{count} - {tags[count]}")
ax.plot(np.cumsum(np.random.randn(33)))
# end of plotting
fig.tight_layout()
pdf.savefig(fig)
pdf.close()
plt.show()
B. Loop over data
Or alternatively you could loop over the tags themselves and create a new figure once it's needed:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
tags = ["".join(np.random.choice(list("ABCDEFG123"), size=5)) for _ in range(53)]
nrows = 5 # number of rows per page
ncols = 4 # number of columns per page
pdf = PdfPages('out2.pdf')
for i, tag in enumerate(tags):
j = i % (nrows*ncols)
if j == 0:
fig = plt.figure(figsize=(8,11))
ax = fig.add_subplot(nrows, ncols,j+1)
ax.set_title(f"{i} - {tags[i]}")
ax.plot(np.cumsum(np.random.randn(33)))
# end of plotting
if j == (nrows*ncols)-1 or i == len(tags)-1:
fig.tight_layout()
pdf.savefig(fig)
pdf.close()
plt.show()
You can use matplotlib's PdfPages as follows.
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
import numpy as np
pp = PdfPages('multipage.pdf')
x=np.arange(1,10)
y=np.arange(1,10)
fig=plt.figure()
ax1=fig.add_subplot(211)
# ax1.set_title("cell" + keyInTags)
# ax1.plot(x, y, color='k')
# ax.plot(x, y_red, color='k')
ax2=fig.add_subplot(212)
pp.savefig(fig)
fig2=plt.figure()
ax1=fig2.add_subplot(321)
ax1.plot(x, y, color='k')
ax2=fig2.add_subplot(322)
ax2.plot(x, y, color='k')
ax3=fig2.add_subplot(313)
pp.savefig(fig2)
pp.close()
Play with these subplot numbers a little bit, so you would understand how to handle which graph goes where.
Hoping to get some help please, I'm trying plot simulation data in separate subplots using pandas and matplotlib my code so far is:
import matplotlib.pylab as plt
import pandas as pd
fig, ax = plt.subplots(2, 3)
for i in range(2):
for j in range(50, 101, 10):
for e in range(3):
Var=(700* j)/ 100
Names1 = ['ig','M_GZ']
Data1 = pd.read_csv('~/File/JTL_'+str(Var)+'/GZ.csv', names=Names1)
ig = Data1['ig']
M_GZ=Data1['M_GZ']
MGZ = Data1[Data1.M_GZ != 0]
ax[i, e].plot(MGZ['ig'][:4], MGZ['M_GZ'][:4], '--v', linewidth=1.75)
plt.tight_layout()
plt.show()
But the code gives me 6 duplicate copies of the same plot:
instead of each iteration of Var having its own plot, I've tried changing the loop and using different variations like:
fig = plt.figure()
for i in range(1, 7):
ax = fig.add_subplot(2, 3, i)
for j in range(50, 101, 10):
Var=(700* j)/ 100
Names1 = ['ig','M_GZ']
Data1 = pd.read_csv('~/File/JTL_'+str(Var)+'/GZ.csv', names=Names1)
ig = Data1['ig']
M_GZ=Data1['M_GZ']
MGZ = Data1[Data1.M_GZ != 0]
ax.plot(MGZ['ig'][:4], MGZ['M_GZ'][:4], '--v', linewidth=1.75)
plt.tight_layout()
plt.show()
but that changes nothing I still get the same plot as above. Any help would be appreciated, I'm hoping that each subplot contains one set of data instead of all six
This is a Link to one of the Dataframes each subdirectory ~/File/JTL_'+str(Var)+'/ contains a copy of this file there are 6 in total
The problem is in your loop
for i in range(2): # Iterating rows of the plot
for j in range(50, 101, 10): # Iterating your file names
for e in range(3): # iterating the columns of the plot
The end result is that you iterate all the columns for each file name
For it two work, you should have only two nesting levels in your loop. Potential code (updated) :
import matplotlib.pylab as plt
import pandas as pd
fig, ax = plt.subplots(2, 3)
for row in range(2):
for col in range(3):
f_index = range(50, 101, 10)[row+1 * col]
print row, col, f_index
Var=(700* f_index)/ 100
Names1 = ['ig','M_GZ']
Data1 = pd.read_csv('~/File/JTL_'+str(Var)+'/GZ.csv', names=Names1)
ig = Data1['ig']
M_GZ=Data1['M_GZ']
MGZ = Data1[Data1.M_GZ != 0]
ax[row, col].plot(MGZ['ig'][:4], MGZ['M_GZ'][:4], '--v',linewidth=1.75)
plt.tight_layout()
plt.show()
I am plotting a confusion matrix with matplotlib with the following code:
from numpy import *
import matplotlib.pyplot as plt
from pylab import *
conf_arr = [[33,2,0,0,0,0,0,0,0,1,3], [3,31,0,0,0,0,0,0,0,0,0], [0,4,41,0,0,0,0,0,0,0,1], [0,1,0,30,0,6,0,0,0,0,1], [0,0,0,0,38,10,0,0,0,0,0], [0,0,0,3,1,39,0,0,0,0,4], [0,2,2,0,4,1,31,0,0,0,2], [0,1,0,0,0,0,0,36,0,2,0], [0,0,0,0,0,0,1,5,37,5,1], [3,0,0,0,0,0,0,0,0,39,0], [0,0,0,0,0,0,0,0,0,0,38] ]
norm_conf = []
for i in conf_arr:
a = 0
tmp_arr = []
a = sum(i,0)
for j in i:
tmp_arr.append(float(j)/float(a))
norm_conf.append(tmp_arr)
plt.clf()
fig = plt.figure()
ax = fig.add_subplot(111)
res = ax.imshow(array(norm_conf), cmap=cm.jet, interpolation='nearest')
cb = fig.colorbar(res)
savefig("confmat.png", format="png")
But I want to the confusion matrix to show the numbers on it like this graphic (the right one). How can I plot the conf_arr on the graphic?
You can use text to put arbitrary text in your plot. For example, inserting the following lines into your code will write the numbers (note the first and last lines are from your code to show you where to insert my lines):
res = ax.imshow(array(norm_conf), cmap=cm.jet, interpolation='nearest')
for i, cas in enumerate(conf_arr):
for j, c in enumerate(cas):
if c>0:
plt.text(j-.2, i+.2, c, fontsize=14)
cb = fig.colorbar(res)
The only way I could really see of doing it was to use annotations. Try these lines:
for i,j in ((x,y) for x in xrange(len(conf_arr))
for y in xrange(len(conf_arr[0]))):
ax.annotate(str(conf_arr[i][j]),xy=(i,j))
before saving the figure. It adds the numbers, but I'll let you figure out how to get the sizes of the numbers how you want them.