Matplotlib show x-ticks on all subplots and unique y label

13,956

Solution 1

There are a couple of things you can do. Either remove sharex = True. Or, if you want to use that, sharex sets the x ticks to not be visible i.e. set_visible(False). Therefore, you can set them to True to stop this.

In order to have the subplots formatted the same, you need to set the tick params for each subplot by using axes[0].tick_params(axis='both', which='both', labelsize=7) for both subplots (i.e. repeat for axes[1])

Note, personally I prefer to use matpotlib object oriented API i.e using ax.set_ylabel() rather than plt.ylabel() as I think it gives more control over which subplots and axes you are using. Therefore I have slightly modified your code in that regards too

df = pd.DataFrame([{'DATETIME': '2017-09-29 01:00,', 'Population': 1000, 'Temp': 90, 'State': 'California'},
                   {'DATETIME': '2017-09-29 01:00,', 'Population': 2000, 'Temp': 70, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 01:00,', 'Population': 3000, 'Temp': 50, 'State': 'Georgia'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 2000, 'Temp': 40, 'State': 'California'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 6000, 'Temp': 20, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 4000, 'Temp': 30, 'State': 'Georgia'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 3000, 'Temp': 40, 'State': 'California'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 4000, 'Temp': 60, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 2000, 'Temp': 80, 'State': 'Georgia'}])

df.index = df['DATETIME']
df.index = (pd.to_datetime(df.index)).strftime("%m/%d %H:00")

fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True)

df.groupby('State')['Population'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[0])
axes[0].set_ylabel('Pop')
df.groupby('State')['Temp'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[1])
axes[1].set_ylabel('Temp')

# Set the formatting the same for both subplots
axes[0].tick_params(axis='both', which='both', labelsize=7)
axes[1].tick_params(axis='both', which='both', labelsize=7)

# set ticks visible, if using sharex = True. Not needed otherwise
for tick in axes[0].get_xticklabels():
    tick.set_visible(True)

plt.tight_layout()
plt.show()

Which gives:

enter image description here

Solution 2

As other answers have mentioned, to get the ylabel showing up on both subplots, you can use the object-oriented interface here axes[0].set_ylabel and axes[1].set_ylabel.

You should also use .tick_params on both axes to get the same size tick labels, etc. for both subplots

And finally, to get the tick labels to show up on the first subplot, as an alternative to looping over all the ticks and having to set them to be visible, you can achieve the same thing by giving just one more option tick_params: labelbottom=True.

fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True)

df.groupby('State')['Population'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[0])
axes[0].set_ylabel('Pop')
df.groupby('State')['Temp'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[1])
axes[1].set_ylabel('Temp')
axes[0].tick_params(axis='both', which='both', labelsize=7, labelbottom=True)
axes[1].tick_params(axis='both', which='both', labelsize=7)

enter image description here

Solution 3

Regarding the first question, I'd advise against that not to clutter the plot with extra ink.

Now, onto the y labels. you have to use the axes you get from plt.subplots replacing

plt.ylabel('Pop') by axes[0].set_ylabel('Pop') and plt.ylabel('Pop') by axes[1].set_ylabel('Temp')

Share:
13,956
MBasith
Author by

MBasith

Updated on June 15, 2022

Comments

  • MBasith
    MBasith almost 2 years

    I am plotting two subplots that share the same x-axis but when I plot I only see the x-axis ticks on the second subplot. How can I make the x-ticks visible on both subplots?

    Also I would like to set y-labels for both subplots but only the second is visible. Can you please help in displaying the y-label on both subplots?

    Below is my reproducible code.

    #!/usr/bin/python3
    import pandas as pd
    desired_width = 1500
    pd.set_option('display.width', desired_width)
    import matplotlib.pyplot as plt
    import numpy as np
    
    
    df = pd.DataFrame([{'DATETIME': '2017-09-29 01:00,', 'Population': 1000, 'Temp': 90, 'State': 'California'},
                       {'DATETIME': '2017-09-29 01:00,', 'Population': 2000, 'Temp': 70, 'State': 'Illinois'},
                       {'DATETIME': '2017-09-29 01:00,', 'Population': 3000, 'Temp': 50, 'State': 'Georgia'},
                       {'DATETIME': '2017-09-29 02:00,', 'Population': 2000, 'Temp': 40, 'State': 'California'},
                       {'DATETIME': '2017-09-29 02:00,', 'Population': 6000, 'Temp': 20, 'State': 'Illinois'},
                       {'DATETIME': '2017-09-29 02:00,', 'Population': 4000, 'Temp': 30, 'State': 'Georgia'},
                       {'DATETIME': '2017-09-29 03:00,', 'Population': 3000, 'Temp': 40, 'State': 'California'},
                       {'DATETIME': '2017-09-29 03:00,', 'Population': 4000, 'Temp': 60, 'State': 'Illinois'},
                       {'DATETIME': '2017-09-29 03:00,', 'Population': 2000, 'Temp': 80, 'State': 'Georgia'}])
    
    df.index = df['DATETIME']
    df.index = (pd.to_datetime(df.index)).strftime("%m/%d %H:00")
    
    fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True)
    
    df.groupby('State')['Population'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[0])
    plt.ylabel('Pop')
    df.groupby('State')['Temp'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[1])
    plt.ylabel('Temp')
    plt.tick_params(axis='both', which='both', labelsize=7)
    plt.tight_layout()
    plt.show()
    

    Current Chart Output:

    enter image description here