How to Make a Barplot and a Lineplot in the Same Seaborn Plot with Different Y Axes Nicely

How can I make a barplot and a lineplot in the same seaborn plot with different Y axes nicely?

You have to remove grid lines of the second axis. Add to the code ax2.grid(False). However y-ticks of the second axis will be not align to y-ticks of the first y-axis, like here:

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

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(pd.Series(np.random.uniform(0,1,size=10)), color='g')
ax2 = ax1.twinx()
ax2.plot(pd.Series(np.random.uniform(0,17,size=10)), color='r')
ax2.grid(False)
plt.show()

Sample Image

How to plot seaborn lineplot and barplot on the same plot with same number of y-axes tickers and both y-axes aligned at 0 in Python

Here are the answers to my questions:

matplotlib.rc_file_defaults()
ax1 = sns.set_style(style=None, rc=None)
fig, ax1 = plt.subplots(figsize=(12,6))
ax2 = ax1.twinx()

# plot the bar plot and make the colours dependent on the values in a seperate column
result_date = result.reset_index()

palette = {"low":"lightgreen",
"mid":"darkseagreen",
"high":"green"}

b_plot = sns.barplot(data = result_date, x=result_date.iloc[:, 0],

y=result_date.iloc[:, 3], ax=ax1, hue='percentile', palette=palette, dodge = False)

# plot the lineplot
a_plot = sns.pointplot(data=result, x=result.index, y=result.iloc[:, 0], color="black", ax=ax2, markers = 'o', scale=0.4)

# set the x tickers to be those of the bar plot
ax1.set_xticks(np.arange(len(result_date)))
ax1.set_xticklabels(result_date.date.apply(lambda x: str(x.year)))
ax1.xaxis.set_major_locator(ticker.AutoLocator())

# align axis at 0, and get same number of ticks on both y-axes
max1 = np.nanmax(np.abs(ax1.get_ybound()))
max2 = np.nanmax(np.abs(ax2.get_ybound()))
nticks = 7

ax1.set_yticks(np.linspace(-max1, max1, nticks))
ax2.set_yticks(np.linspace(-max2, max2, nticks))

Barplot and line plot in seaborn/matplotlib

Since the two scales are vastly different, create a secondary y-axis.

Since bar plots are categorical, seaborn converts the x dates to ordinal ticks. That means matplotlib date formatters will no longer work on them, so it's better to format the date strings beforehand, e.g., dt.date or dt.strftime.

Also since seaborn changes the x-axis to ordinal ticks, it's simplest to create the lines with a pointplot (but if you really want to use a lineplot, reset the index and set x to the numeric range).

fig, ax1 = plt.subplots()
ax2 = ax1.twinx() # secondary y-axis

df['Date'] = df['Date'].dt.date # or dt.strftime('%Y-%m-%d')

sns.barplot(x='Date', y='Col1', data=df, ax=ax1) # on primary ax1
sns.pointplot(x='Date', y='Col2', color='#333', data=df, ax=ax2) # on secondary ax2

# sns.lineplot(x='index', y='Col2', color='#333', data=df.reset_index(), ax=ax2)

Seaborn plotting histogram and lineplot on the same figure with 2 y-axis

You can plot against the index and manually relabel:

fig=plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()

# changes here
sns.barplot(x=myDF.index,y='Frequency',data=myDF,color='blue',ax=ax1)
sns.lineplot(x=myDF.index,y='Cumulative',data=myDF,marker='s',color='orange',ax=ax2)

# and here
plt.xticks(myDF.index, myDF.Bin, rotation=60)
plt.show()

Output:

Sample Image


Update: Actually , you need only change the lineplot command:

fig=plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
sns.barplot(x='Bin',y='Frequency',data=myDF,color='blue',ax=ax1)

# only change this line
sns.lineplot(x=myDF.index, y='Cumulative',data=myDF,marker='s',color='orange',ax=ax2)

plt.xticks(rotation=60)
plt.show()

and also get the same output.

Second y-axis time series seaborn

I would recommend using a normal line plot. You can get a twin axes via ax.twinx().

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({"date": ["2018-01-01", "2018-01-02", "2018-01-03", "2018-01-04"],
"column1": [555,525,532,585],
"column2": [50,48,49,51]})

ax = df.plot(x="date", y="column1", legend=False)
ax2 = ax.twinx()
df.plot(x="date", y="column2", ax=ax2, legend=False, color="r")
ax.figure.legend()
plt.show()

Sample Image



Related Topics



Leave a reply



Submit