This is my code. The issue is that the stacked bar plot is 'in front of' the line plot. I tried setting the zorder of the stacked bar plot to negative and the one of the line plot to positive, but it didn't work.
How can I get the line to be in front of the bars?
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Example DataFrame
data = {
'month_year': ['Jan-2023', 'Feb-2023', 'Mar-2023', 'Apr-2023'],
'gas_share': [30, 25, 20, 35],
'lignite_share': [50, 40, 45, 30],
'coal_share': [20, 35, 35, 35],
'final_residual': [500, 600, 550, 650]
}
df = pd.DataFrame(data)
# Create figure and primary axis
fig, ax1 = plt.subplots(figsize=(10, 6))
# Create a twin axis for the shares (secondary y-axis on the right)
ax2 = ax1.twinx()
# Create a stacked bar plot for the share columns on the secondary y-axis
width = 0.4 # width of bars
bar1 = np.arange(len(df['month_year']))
# Plot stacked bars (secondary y-axis)
ax2.bar(bar1, df['gas_share'], width, label='Gas Share', color='#FF9999', zorder=-1)
ax2.bar(bar1, df['lignite_share'], width, bottom=df['gas_share'], label='Lignite Share', color='#66B2FF', zorder=-1)
ax2.bar(bar1, df['coal_share'], width, bottom=df['gas_share'] + df['lignite_share'], label='Coal Share', color='#99FF99', zorder=-1)
# Set labels and ticks for the secondary axis
ax2.set_ylabel('Share (%)')
ax2.set_xticks(bar1)
ax2.set_xticklabels(df['month_year'])
ax2.tick_params(axis='y')
# Plot 'final_residual' as a line on the primary y-axis (line plot should appear on top)
ax1.plot(df['month_year'], df['final_residual'], color='black', label='Final Residual', marker='o', linewidth=2, zorder=20)
ax1.set_xlabel('Month-Year')
ax1.set_ylabel('Final Residual')
ax1.tick_params(axis='y')
# Add grid to the primary axis
ax1.grid(True)
# Add a legend and move it outside the plot area
fig.legend(loc="upper center", bbox_to_anchor=(0.5, -0), ncol=4)
# Show plot
plt.title("Final Residual and Share % Over Time")
plt.xticks(rotation=45) # Rotate x-axis labels for better readability
plt.tight_layout()
plt.show()
You can also add the following before plt.show()
ax1.set_zorder(1)
ax1.patch.set_visible(False)
If you only need the y axis grid use
ax1.yaxis.grid(True)
Here is the full solution.
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Example DataFrame
data = {
'month_year': ['Jan-2023', 'Feb-2023', 'Mar-2023', 'Apr-2023'],
'gas_share': [30, 25, 20, 35],
'lignite_share': [50, 40, 45, 30],
'coal_share': [20, 35, 35, 35],
'final_residual': [500, 600, 550, 650]
}
df = pd.DataFrame(data)
# Create figure and primary axis
fig, ax1 = plt.subplots(figsize=(10, 6))
# Create a twin axis for the shares (secondary y-axis on the right)
ax2 = ax1.twinx()
# Create a stacked bar plot for the share columns on the secondary y-axis
width = 0.4 # width of bars
bar1 = np.arange(len(df['month_year']))
# Plot stacked bars (secondary y-axis)
ax2.bar(bar1, df['gas_share'], width, label='Gas Share', color='#FF9999', zorder=-1)
ax2.bar(bar1, df['lignite_share'], width, bottom=df['gas_share'], label='Lignite Share', color='#66B2FF', zorder=-1)
ax2.bar(bar1, df['coal_share'], width, bottom=df['gas_share'] + df['lignite_share'], label='Coal Share', color='#99FF99', zorder=-1)
# Set labels and ticks for the secondary axis
ax2.set_ylabel('Share (%)')
ax2.set_xticks(bar1)
ax2.set_xticklabels(df['month_year'])
ax2.tick_params(axis='y')
# Plot 'final_residual' as a line on the primary y-axis (line plot should appear on top)
ax1.plot(df['month_year'], df['final_residual'], color='black', label='Final Residual', marker='o', linewidth=2, zorder=20)
ax1.set_xlabel('Month-Year')
ax1.set_ylabel('Final Residual')
ax1.tick_params(axis='y')
# Add grid to the primary axis
ax1.yaxis.grid(True)
# Set Z of the axis
ax1.set_zorder(1)
ax1.patch.set_visible(False)
# Add a legend and move it outside the plot area
fig.legend(loc="upper center", bbox_to_anchor=(0.5, -0), ncol=4)
# Show plot
plt.title("Final Residual and Share % Over Time")
plt.xticks(rotation=45) # Rotate x-axis labels for better readability
plt.tight_layout()
plt.show()