33

I have two graphs to where both have the same x-axis, but with different y-axis scalings.

The plot with regular axes is the data with a trend line depicting a decay while the y semi-log scaling depicts the accuracy of the fit.

fig1 = plt.figure(figsize=(15,6))
ax1 = fig1.add_subplot(111)

# Plot of the decay model 
ax1.plot(FreqTime1,DecayCount1, '.', color='mediumaquamarine')

# Plot of the optimized fit
ax1.plot(x1, y1M, '-k', label='Fitting Function: $f(t) = %.3f e^{%.3f\t} \
         %+.3f$' % (aR1,kR1,bR1))

ax1.set_xlabel('Time (sec)')
ax1.set_ylabel('Count')
ax1.set_title('Run 1 of Cesium-137 Decay')

# Allows me to change scales
# ax1.set_yscale('log')
ax1.legend(bbox_to_anchor=(1.0, 1.0), prop={'size':15}, fancybox=True, shadow=True)

enter image description here enter image description here

Now, i'm trying to figure out to implement both close together like the examples supplied by this link http://matplotlib.org/examples/pylab_examples/subplots_demo.html

In particular, this one

enter image description here

When looking at the code for the example, i'm a bit confused on how to implant 3 things:

1) Scaling the axes differently

2) Keeping the figure size the same for the exponential decay graph but having a the line graph have a smaller y size and same x size.

For example:

enter image description here

3) Keeping the label of the function to appear in just only the decay graph.

Any help would be most appreciated.

3 Answers 3

52

Look at the code and comments in it:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import gridspec

# Simple data to display in various forms
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

fig = plt.figure()
# set height ratios for subplots
gs = gridspec.GridSpec(2, 1, height_ratios=[2, 1]) 

# the first subplot
ax0 = plt.subplot(gs[0])
# log scale for axis Y of the first subplot
ax0.set_yscale("log")
line0, = ax0.plot(x, y, color='r')

# the second subplot
# shared axis X
ax1 = plt.subplot(gs[1], sharex = ax0)
line1, = ax1.plot(x, y, color='b', linestyle='--')
plt.setp(ax0.get_xticklabels(), visible=False)
# remove last tick label for the second subplot
yticks = ax1.yaxis.get_major_ticks()
yticks[-1].label1.set_visible(False)

# put legend on first subplot
ax0.legend((line0, line1), ('red line', 'blue line'), loc='lower left')

# remove vertical gap between subplots
plt.subplots_adjust(hspace=.0)
plt.show()

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

@Serenity Great answer! But is it possible to have shared x axis if I use fig, axis = plt.subplots(nrows=4) to create my axis array?
Yep, it is possible, why not?
@Serenity Well, I think this is possible if using plt.plot() then I could specify sharex. But in Pandas I cannot get a touch to the underlying sharex, I have to make a new axis to pass for the DataFrame.plot(). That's why I like your answer!
Note that one can create the two axes in one call: fig, (ax0, ax1) = plt.subplots(2,1, sharex=True, gridspec_kw=dict(height_ratios=[2, 1]))
13

Here is my solution:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

fig, (ax1,ax2) = plt.subplots(nrows=2, sharex=True, subplot_kw=dict(frameon=False)) # frameon=False removes frames

plt.subplots_adjust(hspace=.0)
ax1.grid()
ax2.grid()

ax1.plot(x, y, color='r')
ax2.plot(x, y, color='b', linestyle='--')

enter image description here

One more option is seaborn.FacetGrid but this requires Seaborn and Pandas libraries.

Comments

2

Here are some adaptions to show how the code could work to add a combined legend when plotting a pandas dataframe. ax=ax0 can be used to plot on a given ax and ax0.get_legend_handles_labels() gets the information for the legend.

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

dates = pd.date_range('20210101', periods=100, freq='D')
df0 = pd.DataFrame({'x': np.random.normal(0.1, 1, 100).cumsum(),
                    'y': np.random.normal(0.3, 1, 100).cumsum()}, index=dates)
df1 = pd.DataFrame({'z': np.random.normal(0.2, 1, 100).cumsum()}, index=dates)

fig, (ax0, ax1) = plt.subplots(nrows=2, sharex=True, gridspec_kw={'height_ratios': [2, 1], 'hspace': 0})

df0.plot(ax=ax0, color=['dodgerblue', 'crimson'], legend=False)
df1.plot(ax=ax1, color='limegreen', legend=False)

# put legend on first subplot
handles0, labels0 = ax0.get_legend_handles_labels()
handles1, labels1 = ax1.get_legend_handles_labels()
ax0.legend(handles=handles0 + handles1, labels=labels0 + labels1)

# remove last tick label for the second subplot
yticks = ax1.get_yticklabels()
yticks[-1].set_visible(False)

plt.tight_layout()
plt.show()

using pandas plotting

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.