How can I draw 2 subplots into same track? - python

As you can see I'm trying to draw line graphs which gets its data from the dataframe that I created. I want users to see these drawings in the same page. In other words I want to get it as a single output. How can I do it? Thanks.
import matplotlib.pyplot as plt
import pandas as pd
ax1 = plt.subplots(1,1, figsize=(15,5))
ax1 = df2['Su Seviyesi (m)'].plot(use_index= True)
ax1 = df2['KUYU KOTU (m)'].plot(use_index= True, label="KUYU KOTU")
plt.legend(ncol=3, loc="lower left")
ax1.set(xlabel='Tarih', ylabel='Su Seviyesi (m)')
ax1.get_ygridlines()
ax1.get_yticklines(minor=False)
ax2 = plt.subplots(1,1 ,figsize=(15,5))
ax2 = df2['NaHCO3'].plot(use_index= True, grid=True)
ax2 = df2['TA'].plot(use_index= True, grid=True)
ax2 = df2['Na2CO3'].plot(use_index= True, grid=True)
ax2.get_ygridlines()
ax2.get_yticklines(minor=False)
plt.legend(ncol=3, loc="upper right")
plt.grid()
Output :
Output Expectation :

This is what I think you are trying to do.
import matplotlib.pyplot as plt
import pandas as pd
# Note 1: Subplots returns axes objects, unlike `plt.subplot`
# which works more like the Matlab subplot command and needs
# to be called repeatedly to activate each axis
# Note 2: We need a figsize that is twice as high as one axis
# Note 3: For plots like this it helps to share an x axis
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15,10), sharex=True)
# Note 4: Here I am passing through the target axis.
# No need to capture the output here
df2['Su Seviyesi (m)'].plot(ax=ax1, use_index=True)
df2['KUYU KOTU (m)'].plot(ax=ax1, use_index=True, label="KUYU KOTU")
ax1.legend(ncol=3, loc="lower left")
ax1.set(xlabel='Tarih', ylabel='Su Seviyesi (m)')
# Note 5: We can easily plot multiple lines with one call to .plot
# if we just select the right columns.
df2[['NaHCO3', 'TA', 'Na2CO3']].plot(ax=ax2, use_index=True, grid=True)
ax2.legend(ncol=3, loc="upper right")

I solved the problem like this. Thanks for your anwers.
import matplotlib.pyplot as plt
import pandas as pd
fig, (ax1, ax2) = plt.subplots(2, figsize=(15,10))
fig.suptitle('{} Kuyusu Verileri'.format(e1_string))
ax1.plot(df2['NUMUNE'], df2['Su Seviyesi (m)'], label= 'Su Seviyesi (m)')
ax1.plot(df2['NUMUNE'], df2['KUYU KOTU (m)'], label= 'KUYU KOTU (m)')
ax1.get_ygridlines()
ax1.get_yticklines(minor=False)
ax1.legend(loc="upper right")
ax1.grid()
ax2.plot(df2['NUMUNE'], df2['NaHCO3'], label = '% NaHCO3' )
ax2.plot(df2['NUMUNE'], df2['Na2CO3'], label = '% Na2CO3' )
ax2.plot(df2['NUMUNE'], df2['TA'], label = '% TA' )
ax2.get_ygridlines()
ax2.get_yticklines(minor=False)
ax2.legend(loc="upper right")
ax2.grid()

Related

How to add stripplot under boxplot (by default it is always on top) in seaborn?

It seems that stripplot (or swarmplot) are automatically always added on top of boxplot even if I call one function in front of the other.
Am I missing something here? How to make stripplot be behind the boxplot? Also, I am actually only using boxplots to use the 'mean' with diamond marker.
Here is a sample code for how I pretty much call the functions now:
fig, axs = plt.subplots(nrows=1, ncols=1, figsize=(5, 4), dpi=200)
sns.boxplot(ax=axs, data=df, x='region', y='measure', hue='group',
meanprops={'marker' : 'D', 'markeredgecolor' : 'black', 'markersize' : 6},
medianprops={'visible': False}, whiskerprops={'visible': False},
showmeans=True, showfliers=False, showbox=False, showcaps=False)
sns.stripplot(ax=axs, data=df, x='region', y='measure', hue='group',
dodge=True, jitter=0.05)
plt.show()
The plot currently
You can add sns.stripplot(..., zorder=0) to put the strip plot below the other elements.
To have the mean in the legend, you can add a label. As this will label each individual mean, you can collect all the legend handles, and filter out the first of those, together with the PathCollections that represent the dots of the stripplot, also leaving out the rectangles that represent the left-out boxes.
import matplotlib.pyplot as plt
from matplotlib.collections import PathCollection
from matplotlib.lines import Line2D
import seaborn as sns
tips = sns.load_dataset('tips')
fig, axs = plt.subplots(figsize=(5, 4))
sns.boxplot(ax=axs, data=tips, x='day', y='tip', hue='smoker',
meanprops={'marker' : 'D', 'markeredgecolor' : 'black', 'markersize' : 6, 'label':'mean'},
medianprops={'visible': False}, whiskerprops={'visible': False},
showmeans=True, showfliers=False, showbox=False, showcaps=False)
sns.stripplot(ax=axs, data=tips, x='day', y='tip', hue='smoker', palette='autumn',
dodge=True, jitter=0.05, zorder=0)
handles, _ = axs.get_legend_handles_labels()
new_handles = [h for h in handles if isinstance(h, PathCollection)] + [h for h in handles if isinstance(h, Line2D)][:1]
axs.legend(handles=new_handles, title=axs.legend_.get_title().get_text())
plt.show()
if you want two and more plot use
fig, ax = plt.subplots(2,2, figsize=(20, 15))
And use ax=ax[0,1], row and col,
sns.boxplot(x = 'bedrooms', y = 'price', data = dataset_df, ax=ax[0,1])
sns.boxplot(x = 'floor, y = 'price', data = dataset_df, ax=ax[0,2])

Unable to generate legend using python / matlibplot for 4 lines all labelled

Want labels for Bollinger Bands (R) ('upper band', 'rolling mean', 'lower band') to show up in legend. But legend just applies the same label to each line with the pandas label for the first (only) column, 'IBM'.
# Plot price values, rolling mean and Bollinger Bands (R)
ax = prices['IBM'].plot(title="Bollinger Bands")
rm_sym.plot(label='Rolling mean', ax=ax)
upper_band.plot(label='upper band', c='r', ax=ax)
lower_band.plot(label='lower band', c='r', ax=ax)
#
# Add axis labels and legend
ax.set_xlabel("Date")
ax.set_ylabel("Adjusted Closing Price")
ax.legend(loc='upper left')
plt.show()
I know this code may represent a fundamental lack of understanding of how matlibplot works so explanations are particularly welcome.
The problem is most probably that whatever upper_band and lower_band are, they are not labeled.
One option is to label them by putting them as column to a dataframe. This will allow to plot the dataframe column directly.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
y =np.random.rand(4)
yupper = y+0.2
ylower = y-0.2
df = pd.DataFrame({"price" : y, "upper": yupper, "lower": ylower})
fig, ax = plt.subplots()
df["price"].plot(label='Rolling mean', ax=ax)
df["upper"].plot(label='upper band', c='r', ax=ax)
df["lower"].plot(label='lower band', c='r', ax=ax)
ax.legend(loc='upper left')
plt.show()
Otherwise you can also plot the data directly.
import matplotlib.pyplot as plt
import numpy as np
y =np.random.rand(4)
yupper = y+0.2
ylower = y-0.2
fig, ax = plt.subplots()
ax.plot(y, label='Rolling mean')
ax.plot(yupper, label='upper band', c='r')
ax.plot(ylower, label='lower band', c='r')
ax.legend(loc='upper left')
plt.show()
In both cases, you'll get a legend with labels. If that isn't enough, I recommend reading the Matplotlib Legend Guide which also tells you how to manually add labels to legends.

How to sharex and sharey axis in for loop

I'm trying to share the x-axis and y-axis of my sumplots, I've tried using the sharey and sharex several different ways but haven't gotten the correct result.
ax0 = plt.subplot(4,1,1)
for i in range(4):
plt.subplot(4,1,i+1,sharex = ax0)
plt.plot(wavelength[i],flux)
plt.xlim([-1000,1000])
plt.ylim([0,1.5])
plt.subplots_adjust(wspace=0, hspace=0)
plt.show()
If I understood you correctly, want to have four stacked plots, sharing the x-axis and the y-axis. This you can do with plt.subplots and the keywords sharex=True and sharey=True. See example below:
import numpy as np
import matplotlib.pyplot as plt
fig, axlist = plt.subplots(4, 1, sharex=True, sharey=True)
for ax in axlist:
ax.plot(np.random.random(100))
plt.show()

Fitting 3 subplots on the same figure

I am trying to plot 3 subplots on the same figure and for some reason the code I have is not working. The first two appear on the same figure, but the last one doesn't. Can someone help me out:
fig = plt.figure(0, figsize = (12,10))
fig.add_subplot(221)
bike_gender.plot(kind='bar',title='Trip Duration by Gender', figsize= (9,7))
bar_plot.set_ylabel('Trip duration')
bar_plot.set_xlabel('Gender')
bar_plot.xaxis.set_ticklabels(['Men', 'Women', 'Unknown'])
bar_plot.text (0, 400000, 'Men = 647,466', bbox=dict(facecolor='red', alpha=0.5))
bar_plot.text (1, 400000, 'Women = 202,136', bbox=dict(facecolor='red', alpha=0.5))
bar_plot.text (2, 400000, 'Unknown = 119,240', bbox=dict(facecolor='red', alpha=0.5))
fig.add_subplot(222)
labels = 'Subscriber \n (849,778)', 'Customer \n (119,064)'
pie_chart = bike_user.plot(kind='pie', title= 'Breakdown of usertype', labels = labels, autopct='%1.1f%%', figsize=(9,7))
fig.add_subplot(212)
frequencies.plot(kind='bar',color=['blue','yellow','green'], figsize=(12, 4), stacked=True)
plt.show()
An alternative way is to use gridspec
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure()
data = pd.DataFrame(np.random.rand(10,2))
gs = gridspec.GridSpec(2,2)
ax1=fig.add_subplot(gs[0,0])
ax2=fig.add_subplot(gs[0,1])
ax3=fig.add_subplot(gs[1,:])
data.plot(ax = ax1)
data.plot(ax = ax2)
data.plot(ax = ax3)
plt.show()
The last plot should actually appears on the figure, but behind the second one.
It's because your third subplot is in a grid whose shape differs from what you already use. You first 2 plots are on a 2x2 grid (add_subplot(22.)) while the last one is on a 2x1 grid (add_subplot(21.)).
As a quick fix, you can try for your last plot:
fig.add_subplot(223)
And it should work.
However, you seems to want to make plot with pandas and display them in a specific axes of a figure with subplots. To do so you should use:
fig, ax = plt.subplots(2,2, figsize=(12,10))
bike_gender.plot(kind="bar", ax=ax[0], title='Trip Duration by Gender')
bike_user.plot(kind='pie', ax=ax[1], title= 'Breakdown of usertype')
frequencies.plot(kind='bar', ax=ax[2], color=['blue','yellow','green'], stacked=True)
HTH

How to add a title to each subplot

I have one figure which contains many subplots.
fig = plt.figure(num=None, figsize=(26, 12), dpi=80, facecolor='w', edgecolor='k')
fig.canvas.set_window_title('Window Title')
# Returns the Axes instance
ax = fig.add_subplot(311)
ax2 = fig.add_subplot(312)
ax3 = fig.add_subplot(313)
How do I add titles to the subplots?
fig.suptitle adds a title to all graphs and although ax.set_title() exists, the latter does not add any title to my subplots.
Thank you for your help.
Edit:
Corrected typo about set_title(). Thanks Rutger Kassies
ax.title.set_text('My Plot Title') seems to work too.
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax1.title.set_text('First Plot')
ax2.title.set_text('Second Plot')
ax3.title.set_text('Third Plot')
ax4.title.set_text('Fourth Plot')
plt.show()
ax.set_title() should set the titles for separate subplots:
import matplotlib.pyplot as plt
if __name__ == "__main__":
data = [1, 2, 3, 4, 5]
fig = plt.figure()
fig.suptitle("Title for whole figure", fontsize=16)
ax = plt.subplot("211")
ax.set_title("Title for first plot")
ax.plot(data)
ax = plt.subplot("212")
ax.set_title("Title for second plot")
ax.plot(data)
plt.show()
Can you check if this code works for you? Maybe something overwrites them later?
A shorthand answer assuming
import matplotlib.pyplot as plt:
plt.gca().set_title('title')
as in:
plt.subplot(221)
plt.gca().set_title('title')
plt.subplot(222)
etc...
Then there is no need for superfluous variables.
If you want to make it shorter, you could write :
import matplotlib.pyplot as plt
for i in range(4):
plt.subplot(2,2,i+1).set_title(f'Subplot n°{i+1}')
plt.show()
It makes it maybe less clear but you don't need more lines or variables
A solution I tend to use more and more is this one:
import matplotlib.pyplot as plt
fig, axs = plt.subplots(2, 2) # 1
for i, ax in enumerate(axs.ravel()): # 2
ax.set_title("Plot #{}".format(i)) # 3
Create your arbitrary number of axes
axs.ravel() converts your 2-dim object to a 1-dim vector in row-major style
assigns the title to the current axis-object
fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=1, ncols=4,figsize=(11, 7))
grid = plt.GridSpec(2, 2, wspace=0.2, hspace=0.5)
ax1 = plt.subplot(grid[0, 0])
ax2 = plt.subplot(grid[0, 1:])
ax3 = plt.subplot(grid[1, :1])
ax4 = plt.subplot(grid[1, 1:])
ax1.title.set_text('First Plot')
ax2.title.set_text('Second Plot')
ax3.title.set_text('Third Plot')
ax4.title.set_text('Fourth Plot')
plt.show()
In case you have multiple images and you want to loop though them and show them 1 by 1 along with titles - this is what you can do. No need to explicitly define ax1, ax2, etc.
The catch is you can define dynamic axes(ax) as in Line 1 of code
and you can set its title inside a loop.
The rows of 2D array is length (len) of axis(ax)
Each row has 2 items i.e. It is list within a list (Point No.2)
set_title can be used to set title, once the proper axes(ax) or subplot is selected.
import matplotlib.pyplot as plt
fig, ax = plt.subplots(2, 2, figsize=(6, 8))
for i in range(len(ax)):
for j in range(len(ax[i])):
## ax[i,j].imshow(test_images_gr[0].reshape(28,28))
ax[i,j].set_title('Title-' + str(i) + str(j))
You are able to give every graph a different title and label by Iteration only.
titles = {221: 'First Plot', 222: 'Second Plot', 223: 'Third Plot', 224: 'Fourth Plot'}
fig = plt.figure()
for x in range(221,225):
ax = fig.add_subplot(x)
ax.title.set_text(titles.get(x))
plt.subplots_adjust(left=0.1,
bottom=0.1,
right=0.9,
top=0.9,
wspace=0.4,
hspace=0.4)
plt.show()
Output:
As of matplotlib 3.4.3, the Figure.add_subplot function supports kwargs with title as:
fig.add_subplot(311, title="first")
fig.add_subplot(312, title="second")
For completeness, the requested result can also be achieve without explicit reference to the figure axes as follows:
import matplotlib.pyplot as plt
plt.subplot(221)
plt.title("Title 1")
plt.subplot(222)
plt.title("Title 2")
plt.subplot(223)
plt.title("Title 3")
plt.subplot(224)
plt.title("Title 4")
Use plt.tight_layout() after the last plot if you have issues with overlapping labels.

Categories