Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Pandas plots layer order changed by secondary_y

I'm trying to merge a line plot and a bar plot into one plot. The data source is a pandas dataframe.

Here is a demo:

import pandas as pd
test = {"index": range(10), 
        "line": [i**2 for i in range(10)], 
        "bar": [i*10 for i in range(10)]}
test=pd.DataFrame(test)
ax=test.plot(x="index",y="line")
test.plot(x="index",y="bar",color="r",kind="bar",ax=ax)

Everything is good until now, you can see the line is above the bars. If I ask the barplot using the secondary yaxis on the right by changing the last line as:

test.plot(x="index",y="bar",color="r",kind="bar",ax=ax, secondary_y=True)

Then the bars will on top of the line which is not what I desired.

Here are the two plots:

Use only one y axis Use both left and right y axis

I tried to plot the bars first and then plot the line and I also tried to use zorder to force the line above the bar but neither of them work.

Any suggestions or help would be appreciated.

like image 644
TooYoung Avatar asked Apr 13 '17 16:04

TooYoung


People also ask

What is Panda rot?

rot : This keyword argument allows to rotate the markings on the x axis for a horizontal plotting and y axis for a vertical plotting. fontsize : Allows to set the font size for the labels and axis points. colormap : This keyword argument allows to choose different colour sets for the plots.

How do you reset the index of a data frame?

Use DataFrame.reset_index() function reset_index() to reset the index of the updated DataFrame. By default, it adds the current row index as a new column called 'index' in DataFrame, and it will create a new row index as a range of numbers starting at 0.

How do I sort pandas DataFrame?

In order to sort the data frame in pandas, function sort_values() is used. Pandas sort_values() can sort the data frame in Ascending or Descending order.


1 Answers

The second axes will always be on top of the first. So you need to plot the line plot last to have it appear on top of the bars. You may consider the following solution, which sets the line to the secondary scale:

import pandas as pd
test = {"index": range(10), 
        "line": [i**2 for i in range(10)], 
        "bar": [100*i*10 for i in range(10)]}
test=pd.DataFrame(test)

ax  = test.plot(x="index",y="bar",color="r",kind="bar")
ax2 = test.plot(x="index",y="line", color="b", ax=ax, secondary_y=True)
ax.set_ylabel("bar", color="r")
ax2.set_ylabel("line", color="b")

enter image description here

If you then want to have the scale for line on the left side of the plot, you can exchange the scales afterwards:

import pandas as pd
test = {"index": range(10), 
        "line": [i**2 for i in range(10)], 
        "bar": [100*i*10 for i in range(10)]}
test=pd.DataFrame(test)

ax  = test.plot(x="index",y="bar",color="r",kind="bar")
ax2 = test.plot(x="index",y="line", color="b", ax=ax, secondary_y=True)

ax.yaxis.tick_right()
ax2.yaxis.tick_left()
ax.set_ylabel("bar", color="r")
ax2.set_ylabel("line", color="b")
ax.yaxis.set_label_position("right")
ax2.yaxis.set_label_position("left")

enter image description here

like image 80
ImportanceOfBeingErnest Avatar answered Oct 12 '22 23:10

ImportanceOfBeingErnest