BRMBU
BRMBU

Reputation: 31

Jupyter - merge 2 plots with same x-axis

I have generated the following plot with matplotlib from Jupyter. The plots have the same x-axis so I want to merge them, i.e. to have a common x-axis for both the plots.

plot This is the code I have used. How to integrate the result in this code?

import numpy as np 
import pandas as pd
from scipy.optimize import curve_fit    
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
from matplotlib.colors import ListedColormap, LinearSegmentedColormap

file1 = '1.dat'
file2 = '1SED.dat'

data1 = pd.read_csv(file1, delimiter='\s+', header=None, engine='python')
data1.columns = ['Wavelength','Obs.Flux','Obs.Error','Flux','Error','FluxMod','Fitted','Excess','(F-Fm)']

data2 = pd.read_csv(file2, delimiter='\s+', header=None, engine='python')
data2.columns = ['wave','cflux']


def fit_data():

fig = plt.figure(1,figsize=(10,9))

plt.subplot(211)
np.linspace(1000,3E4)
plt.plot(data2['wave'], data2['cflux'],   color='cornflowerblue', linestyle= '-', lw=0.5)
plt.scatter(data1['Wavelength'], data1['Obs.Flux'],  marker='o', color='red', s=75)

#plt.xlabel('$\lambda (\AA)$',size=15)
plt.ylabel('$F_{\lambda} (erg/cm^{2}/s/\AA)$',size=15)
plt.yscale('log')
plt.xscale('log')
plt.ylim(1E-18,4E-17)
plt.xlim(1000,2E4)
plt.title('Star No. 1')

plt.subplot(212)
plt.plot(data1['Wavelength'], data1['(F-Fm)'],  marker='o', color='red')
plt.plot(data1['Wavelength'], data1['(F-Fm)'],  linestyle='-', color='red', lw=1.5)
plt.xlabel('$\lambda (\AA)$',size=15)
plt.xscale('log')

plt.savefig("1SED")

plt.show()
plt.close()

fit_data()

I tried using the edit you suggested and have received the following error

TypeError                                 Traceback (most recent call last)
<ipython-input-8-d43e496e030f> in <module>()
     32     plt.close()
     33 
---> 34 fit_data()


<ipython-input-8-d43e496e030f> in fit_data()
     16 #... other commands to be applied on ax1
     17 
---> 18     ax2 = fig.add_subplot(212, sharex=True)
     19     ax2.plot(data1['Wavelength'], data1['(F-Fm)'],  marker='o', color='red')
     20     ax2.plot(data1['Wavelength'], data1['(F-Fm)'],  linestyle='-', color='red', lw=1.5)

~/anaconda3/lib/python3.6/site-packages/matplotlib/figure.py in add_subplot(self, *args, **kwargs)
   1072                     self._axstack.remove(ax)
   1073 
-> 1074             a = subplot_class_factory(projection_class)(self, *args, **kwargs)
   1075 
   1076         self._axstack.add(key, a)

~/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_subplots.py in __init__(self, fig, *args, **kwargs)
     71 
     72         # _axes_class is set in the subplot_class_factory
---> 73         self._axes_class.__init__(self, fig, self.figbox, **kwargs)
     74 
     75     def __reduce__(self):

~/anaconda3/lib/python3.6/site-packages/matplotlib/axes/_base.py in __init__(self, fig, rect, facecolor, frameon, sharex, sharey, label, xscale, yscale, axisbg, **kwargs)
    496         self._sharey = sharey
    497         if sharex is not None:
--> 498             self._shared_x_axes.join(self, sharex)
    499             if sharex._adjustable == 'box':
    500                 sharex._adjustable = 'datalim'

~/anaconda3/lib/python3.6/site-packages/matplotlib/cbook/__init__.py in join(self, a, *args)
   1493 
   1494         for arg in args:
-> 1495             set_b = mapping.get(ref(arg))
   1496             if set_b is None:
   1497                 set_a.append(ref(arg))

TypeError: cannot create weak reference to 'bool' object

Upvotes: 0

Views: 2201

Answers (1)

OriolAbril
OriolAbril

Reputation: 8773

To personalize the subplots like this, the object oriented API of matplotlib makes the code much simpler.

You already have fig = plt.figure(..., then you would need to do ax1 = fig.add_subplot(211) and modify most of the methods called, in general, adding a set_ in front of the name (i.e. xlabel, yscale, title...) works, in case of doubt, consult the axes class documentation.

In addition, the answers from the other links I commented can be used. The main differences with the code above are using sharex=True in order to force both subplots to have the same xaxis, and after plotting, using the setp and subplots_adjust to remove the labels and the space.

Therefore, the code would look like:

fig = plt.figure(1,figsize=(10,9))

ax1= fig.add_subplot(211)
ax1.plot(data2['wave'], data2['cflux'],   color='cornflowerblue', linestyle= '-', lw=0.5)
ax1.scatter(data1['Wavelength'], data1['Obs.Flux'],  marker='o', color='red', s=75)

ax1.set_ylabel('$F_{\lambda} (erg/cm^{2}/s/\AA)$',size=15)
ax1.set_yscale('log')
#... other commands to be applied on ax1

ax2 = fig.add_subplot(212, sharex=ax1)
#... other commands to be applied on ax2

plt.setp(ax1.get_xticklabels(), visible=False) # hide labels
fig.subplots_adjust(hspace=0) # remove vertical space between subplots

Upvotes: 1

Related Questions