Perhaps the title is misleading or someone will come along telling me that is duplicated. However after many (many) hours of browsing I haven't found anything. I want to plot multiple scatter diagrams and merge them up into a subplot for some nrows and ncols?
Assume that we have the following:
new_list=[]
for j in list(set(lala)):
df1 = df[df['Date'] == j]
df1.drop('Date', axis = 1, inplace = True)
df2 = df1.groupby('Z').mean()
df2.reset_index(inplace = True)
new_list.append(df2)
for j in range(0, len(new_list)):
plt.figure(figsize=(6, 6), dpi=80)
plt.scatter(new_list[j]['X'],new_list[j]['Y'])
and let me explain a little bit of what it does; I create a list called new_list, which contains data frames constructed in the for loop (you can ignore the construction since I'm asking for a global approach). Afterwards, I print scatter diagrams (in total as many as the number of elements of new_list) for each data frame in new_list.
Because the number of the printouts is big, I want to create subplots off these printouts to make the final image easier for the eye.
So how can I take all these scatter diagrams and merge them up into a subplot for some nrows and ncols?
Assuming you have 4 rows and 10 columns, you can do something like this (just one way of doing it). Here flatten returns you a list of 40 axis objects (4 x 10) where the order is across the row: first row four columns first, then second row four columns, and so on.
fig, axes = plt.subplots(nrows=4, ncols=10)
for i, ax in enumerate(axes.flatten()):
ax.scatter(new_list[i]['X'],new_list[i]['Y'])
If you don't want to use enumerate, alternatively you can also use the following
fig, axes = plt.subplots(nrows=4, ncols=10)
ax = axes.flatten()
for j in range(0, len(new_list)):
ax[j].scatter(new_list[j]['X'],new_list[j]['Y'])
Related
I'm trying to generate a plot in seaborn using a for loop to plot the contents of each dataframe column on its own row.
The number of columns that need plotting can vary between 1 and 30. However, the loop creates multiple individual plots, each with their own x-axis, which are not aligned and with a lot of wasted space between the plots. I'd like to have all the plots together with a shared x-axis without any vertical spacing between each plot that I can then save as a single image.
The code I have been using so far is below.
comp_relflux = measurements.filter(like='rel_flux_C', axis=1) *# Extracts relevant columns from larger dataframe
comp_relflux=comp_relflux.reindex(comp_relflux.mean().sort_values().index, axis=1) # Sorts into order based on column mean.
plt.rcParams["figure.figsize"] = [12.00, 1.00]
for column in comp_relflux.columns:
plt.figure()
sns.scatterplot((bjd)%1, comp_relflux[column], color='b', marker='.')
This is a screenshot of the resultant plots.
I have also tried using FacetGrid, but this just seems to plot the last column's data.
p = sns.FacetGrid(comp_relflux, height=2, aspect=6, despine=False)
p.map(sns.scatterplot, x=(bjd)%1, y=comp_relflux[column])
To combine the x-axis labels and have just one instead of having it for each row, you can use sharex. Also, using plt.subplot() to the number of columns you have, you would also be able to have just one figure with all the subplots within it. As there is no data available, I used random numbers below to demonstrate the same. There are 4 columns of data in my df, but have kept as much of your code and naming convention as is. Hope this is what you are looking for...
comp_relflux = pd.DataFrame(np.random.rand(100, 4)) #Random data - 4 columns
bjd=np.linspace(0,1,100) # Series of 100 points - 0 to 1
rows=len(comp_relflux.columns) # Use this to get column length = subplot length
fig, ax = plt.subplots(rows, 1, sharex=True, figsize=(12,6)) # The subplots... sharex is assigned here and I move the size in here from your rcParam as well
for i, column in enumerate(comp_relflux.columns):
sns.scatterplot((bjd)%1, comp_relflux[column], color='b',marker='.', ax=ax[i])
1 output plot with 4 subplots
I have a dataframe with 4 columns and I want to plot each two columns in combination as line plots. The columns are independent of each other. But I want to plot them pairwise.
This would eventually give me an n*n grid of subplots, which looks like this
4x4 gridplot using matplotlib subplot
This was generated using the following code. Since I can not upload the original df, I have created a fake one here.
Number_1 = np.random.uniform(0.5, 0, 30)
Number_2 = np.random.uniform(0.5, 0.25, 30)
Number_3 = np.random.uniform(-0.25, 0.25, 30)
Number_4 = np.random.uniform(0.25, 0, 30)
columns = ['Number_1','Number_2','Number_3','Number_4']
loadings = pd.DataFrame([Number_1,Number_2,Number_3,Number_4]).T
loadings.columns = columns
fig, axs = plt.subplots(loadings.shape[1], loadings.shape[1],figsize=(20,12),tight_layout=True)
fig.suptitle('Loading diagram for each component', fontsize=25)
for i in range(axs.shape[0]):
for j in range(axs.shape[1]):
if i!=j:
axs[i,j].plot(loadings[columns[i]],label=columns[i])
axs[i,j].plot(loadings[columns[j]],label=columns[j])
axs[i,j].legend()
axs[i,j].set_xlabel('x axis title')
else:
axs[i,j].axis('off')
plt.show()
But what I could not figure out was how I could add an outer common axis title for each row and column of the grid. What I want would eventually look like this desired result. Notice the Number_1, Number_2 etc. titles on the outer axes.
One thing that I found on matplotlib was using subfigures. But I could not figure out (pun intended) how to create both horizontal and vertical figures and then name them. I would really appreciate the help. Thank you very much!
The information below may be superfluous if you are trying to understand the error message. Please start off by reading the answer
by #user707650.
Using MatPlotLib, I wanted a generalizable script that creates the following from my data.
A window containing a subplots arranged so that there are b subplots per column. I want to be able to change the values of a and b.
If I have data for 2a subplots, I want 2 windows, each with the previously described "a subplots arranged according to b subplots per column".
The x and y data I am plotting are floats stored in np.arrays and are structured as follows:
The x data is always the same for all plots and is of length 5.
'x_vector': [0.000, 0.005, 0.010, 0.020, 0.030, 0.040]
The y data of all plots are stored in y_vector where the data for the first plot is stored at indexes 0 through 5. The data for the second plot is stored at indexes 6 through 11. The third plot gets 12-18, the fourth 19-24, and so on.
In total, for this dataset, I have 91 plots (i.e. 91*6 = 546 values stored in y_vector).
Attempt:
import matplotlib.pyplot as plt
# Options:
plots_tot = 14 # Total number of plots. In reality there is going to be 7*13 = 91 plots.
location_of_ydata = 6 # The values for the n:th plot can be found in the y_vector at index 'n*6' through 'n*6 + 6'.
plots_window = 7 # Total number of plots per window.
rows = 2 # Number of rows, i.e. number of subplots per column.
# Calculating number of columns:
prim_cols = plots_window / rows
extra_cols = 0
if plots_window % rows > 0:
extra_cols = 1
cols = prim_cols + extra_cols
print 'cols:', cols
print 'rows:', rows
# Plotting:
n=0
x=0
fig, ax = plt.subplots(rows, cols)
while x <= plots_tot:
ax[x].plot(x_vector, y_vector[n:(n+location_of_ydata)], 'ro')
if x % plots_window == plots_window - 1:
plt.show() # New window for every 7 plots.
n = n+location_of_ydata
x = x+1
I get the following error:
cols: 4
rows: 2
Traceback (most recent call last):
File "Script.py", line 222, in <module>
ax[x].plot(x_vector, y_vector[n:(n+location_of_ydata)], 'ro')
AttributeError: 'numpy.ndarray' object has no attribute 'plot'
If you debug your program by simply printing ax, you'll quickly find out that ax is a two-dimensional array: one dimension for the rows, one for the columns.
Thus, you need two indices to index ax to retrieve the actual AxesSubplot instance, like:
ax[1,1].plot(...)
If you want to iterate through the subplots in the way you do it now, by flattening ax first:
ax = ax.flatten()
and now ax is a one dimensional array. I don't know if rows or columns are stepped through first, but if it's the wrong around, use the transpose:
ax = ax.T.flatten()
Of course, by now it makes more sense to simply create each subplot on the fly, because that already has an index, and the other two numbers are fixed:
for x < plots_tot:
ax = plt.subplot(nrows, ncols, x+1)
Note: you have x <= plots_tot, but with x starting at 0, you'll get an IndexError next with your current code (after flattening your array). Matplotlib is (unfortunately) 1-indexed for subplots. I prefer using a 0-indexed variable (Python style), and just add +1 for the subplot index (like above).
The problem here is with how matplotlib handles subplots. Just do the following:
fig, axes = plt.subplots(nrows=1, ncols=2)
for axis in axes:
print(type(axis))
you will get a matplotlib object which is actually a 1D array which can be traversed using single index i.e. axis[0], axis[1]...and so on. But if you do
fig, axes = plt.subplots(nrows=2, ncols=2)
for axis in axes:
print(type(axis))
you will get a numpy ndarray object which is actually a 2D array which can be traversed only using 2 indices i.e. axis[0, 0], axis[1, 0]...and so on. So be mindful how you incorporate your for loop to traverse through axes object.
In case if you use N by 1 graphs, for example if you do like fig, ax = plt.subplots(3, 1) then please do likeax[plot_count].plot(...)
The axes are in 2-d, not 1-d so you can't iterate through using one loop. You need one more loop:
fig,axes=plt.subplots(nrows=2,ncols=2)
plt.tight_layout()
for ho in axes:
for i in ho:
i.plot(a,a**2)
This gives no problem but if I try:
for i in axes:
i.plot(a,a**2)
the error occurs.
I'm trying to plot in a single image, multiple columns of a table.
The idea is to optimize the process with a loop.
It is important to note that all the columns share the same y-axis, and that the x scale varies for each column.
The Final result should look something like this:
I've already tried some things, but with no success, in my code I'm creating several figures, only plotting in the first graph:
def facies_plot_all(logs):
logs = sort_values(by='y')
ztop=logs.Y.min(); zbot=logs.Y.max()
for col in logs.columns:
numcol = (logs.shape[1])
f, ax = plt.subplots (nrows=1, ncols=numcol, figsize (20,25))
ax[x+1].plot(logs[col],logs.Y,'-')
I'm relatively new to programming and still searching for a way to solve this issue.
Any help will be welcome!
Put subplots outside of for loop:
logs = sort_values(by='y')
ztop=logs.Y.min(); zbot=logs.Y.max()
numcol = (logs.shape[1])
f, axes es= plt.subplots (nrows=1, ncols=numcol,
sharey=True,
figsize=(20,25))
for (ax, col) in zip(axes,logs.columns):
ax.plot(logs[col],logs.Y,'-')
I have a seemingly simple problem of standardizing and labeling my axis on a series of graphs I am creating from a DataFrame. This dataframe contains a column with a sort of ID and each row contains a value for x and a value for y. I am generating a separate graph for each ID; however, I would like a standard axis across all of these graphs. Here is my code:
groups = data.groupby('Pedigree')
for Pedigree,group in groups:
group.plot(x='EnvironmentalIndex',y='GrainYield',marker='o',linestyle='',color ='white',label=Pedigree)
plt.plot([0,250],[0,250],linestyle = 'dashed',color='black')
x = group.EnvironmentalIndex
y = group.GrainYield
z = np.polyfit(x,y,1)
p = np.poly1d(z)
q = sum(y)/len(y)
plt.plot(x,p(x),color='green')
plt.text(25,220,'Stability=%.6f'%(z[0]))
plt.text(25,205,'Mean Yield=%.6f'%(q))
I know there is an axes function in Matplotlib, but I can't get the formatting right so that it plays well with the for loop. I have tried inserting a
group.axes()
inside of the for loop but I get the error that the list object is not callable.
If you mean by standard having the same ticks, there are different ways of doing this, one is, if you don't have a lot of plots, create a subplot that shares the same x-axis,
no_rows = len(data.groupby('Pedigree'))
no_columns = 1
fig, ax = plt.subplots(no_rows, no_columns, sharex = True)
ax = ax.reshape(-1)
count = 0
for Pedigree,group in groups:
...
q = sum(y)/len(y)
ax[count].plot(x,p(x),color='green')
ax[count].text(25,220,'Stability=%.6f'%(z[0]))
ax[count].text(25,205,'Mean Yield=%.6f'%(q))
count+=1
Only the xticks from the bottom plot will be applied, you can also define a different number of columns but make sure no_rows * no_columns >= # of plots.