0

Intro

I am new to python, matplotlib and pandas. I spent a lot of time reviewing material to come up with the following. And I am stuck.

Question:

I am trying to plot using pandas. I have three Y axis and of which one is log scale. I cannot figure out why the log function(1) and label function(2) doesn't work for my secondary axis ax2 in the code. It works everywhere else.

All the legends are separated (3). Is there a simpler way to handle this other than do manually.

When I plot the secondary axis part, separately it comes out fine. I ran the plot removing third axis, still problem persists. I put here the code with all axis as I need the solution proposed to work together in this manner.

Here methods are given for solving (3) alone but I am particularly looking for dataframe based plotting. Also other manual techniques are given in the same site, which I do not want to use!

enter image description here

Code and explanation

# Importing the basic libraries
import matplotlib.pyplot as plt
from pandas import DataFrame

# test3 = Dataframe with 5 columns
test3 = df.ix[:,['tau','E_tilde','Max_error_red','time_snnls','z_t_gandb']]

# Setting up plot with 3 'y' axis
fig, ax = plt.subplots()
ax2, ax3 = ax.twinx(), ax.twinx()
rspine = ax3.spines['right']
rspine.set_position(('axes', 1.25))
ax3.set_frame_on(True)
ax3.patch.set_visible(False)
fig.subplots_adjust(right=0.75)

# Setting the color and labels
ax.set_xlabel('tau(nounit)')
ax.set_ylabel('Time(s)', color = 'b')
ax2.set_ylabel('Max_error_red', color = 'r')
ax3.set_ylabel('E_tilde', color = 'g')

# Setting the logscaling
ax.set_xscale('log') # Works 
ax2.set_yscale('log')# Doesnt work

# Plotting the dataframe
test3.plot(x = 'tau', y = 'time_snnls', ax=ax, style='b-')
test3.plot(x = 'tau', y = 'Max_error_red', ax=ax2, style='r-', secondary_y=True)
test3.plot(x = 'tau', y = 'z_t_gandb', ax=ax, style='b-.')
test3.plot(x = 'tau', y = 'E_tilde', ax=ax3, style='g-')
Community
  • 1
  • 1
agent18
  • 2,109
  • 4
  • 20
  • 34

1 Answers1

1

The issue is the secondary_y=True option. Remove that, and it works fine. I think the problem is that you have already set up your twin axes, and having secondary_y=True is interfering with that.

As for the legend: set legend=False in each of your test3.plot commands, and then gather then legend handles and labels from the axes after you have made the plot using ax.get_legend_handles_labels(). Then you can plot them all on one legend.

Finally, to make sure the axes labels are set correctly, you must set them after you have plotted your data, as the pandas DataFrame plotting methods will overwrite whatever you have tried to set. By doing this afterwards, you make sure that it is your label that is set.

Heres a working script (with dummy data):

import matplotlib.pyplot as plt
from pandas import DataFrame
import numpy as np

# Fake up some data
test3 = DataFrame({
    'tau':np.logspace(-3,0,100),
    'E_tilde':np.linspace(100,0,100),
    'Max_error_red':np.logspace(-2,1,100),
    'time_snnls':np.linspace(5,0,100),
    'z_t_gandb':np.linspace(16,15,100)
    })

# Setting up plot with 3 'y' axis
fig, ax = plt.subplots()
ax2, ax3 = ax.twinx(), ax.twinx()
rspine = ax3.spines['right']
rspine.set_position(('axes', 1.25))
ax3.set_frame_on(True)
ax3.patch.set_visible(False)
fig.subplots_adjust(right=0.75)

# Setting the logscaling
ax.set_xscale('log') # Works 
ax2.set_yscale('log')# Doesnt work

# Plotting the dataframe
test3.plot(x = 'tau', y = 'time_snnls', ax=ax, style='b-',legend=False)
test3.plot(x = 'tau', y = 'Max_error_red', ax=ax2, style='r-',legend=False)
test3.plot(x = 'tau', y = 'z_t_gandb', ax=ax, style='b-.',legend=False)
test3.plot(x = 'tau', y = 'E_tilde', ax=ax3, style='g-',legend=False)

# Setting the color and labels
ax.set_xlabel('tau(nounit)')
ax.set_ylabel('Time(s)', color = 'b')
ax2.set_ylabel('Max_error_red', color = 'r')
ax3.set_ylabel('E_tilde', color = 'g')

# Gather all the legend handles and labels to plot in one legend
l1 = ax.get_legend_handles_labels()
l2 = ax2.get_legend_handles_labels()
l3 = ax3.get_legend_handles_labels()

handles = l1[0]+l2[0]+l3[0]
labels = l1[1]+l2[1]+l3[1]

ax.legend(handles,labels,loc=5)

plt.show()

enter image description here

tmdavison
  • 64,360
  • 12
  • 187
  • 165
  • Wow, thank you for yourquick and working response, Just one more thing the xlabel still doesn't change. It is 'tau' as opposed to 'tau(nounit)'. Do you know what's going on there? Do we need to again gather? What is the method used for that? Thank you. – agent18 Apr 16 '16 at 06:31
  • 1
    Try moving the `ax.set_xlabel` line to after the `test3.plot` lines – tmdavison Apr 16 '16 at 09:57
  • 1
    @ThejKiran: I've just confirmed that moving the `set_{x,y}label` lines to after the `plot` lines does indeed fix this issue. See my edit – tmdavison Apr 18 '16 at 10:30