Hardik Dhuri
Hardik Dhuri

Reputation: 377

How do I shade the region between the two line graph

I am facing a problem in shading the region between the two line graphs as they both have different values of dates(x-axis).

Here is the code:

plt.figure(figsize=(30,20))
fig, ax = plt.subplots(1)

plt.plot(highs['Date'], highs['Data_Value'], label = "Record High")
plt.plot(lows['Date'], lows['Data_Value'], label = "Record Low")
plt.scatter(tmin2015['Date'].tolist(), tmin2015['Data_Value'], marker='o', c='green', label="2015 record low")
x = plt.gca().xaxis
plt.xlabel("Year", fontsize=16)
plt.ylabel("Temperature in \N{DEGREE SIGN}C", fontsize=16)
plt.title("Extreme Temperature Recorded Every Year")

for item in x.get_ticklabels():
    item.set_rotation(45)
plt.legend(loc='best')

# ax.fill_between(highs['Date'],lows['Data_Value'], highs['Data_Value'])
plt.show()

enter image description here

Upvotes: 1

Views: 234

Answers (2)

Scott Boston
Scott Boston

Reputation: 153510

Similiar to the "interpolating method" mentioned by @MrT:

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

df_high = pd.DataFrame({'Date':pd.date_range('2020-01-01',  periods=100, freq='3D'),
                       'data_value':400+np.random.randint(0,20, 100)})

df_low = pd.DataFrame({'Date':pd.date_range('2020-03-03',  periods=100, freq='3D'),
                       'data_value':-200+np.random.randint(0,20, 100)})

plt.figure(figsize=(30,20))
fig, ax = plt.subplots(1)

plt.plot(df_high['Date'], df_high['data_value'], label = "Record High")
plt.plot(df_low['Date'], df_low['data_value'], label = "Record Low")
# plt.scatter(tmin2015['Date'].tolist(), tmin2015['Data_Value'], marker='o', c='green', label="2015 record low")
x = plt.gca().xaxis
plt.xlabel("Year", fontsize=16)
plt.ylabel("Temperature in \N{DEGREE SIGN}C", fontsize=16)
plt.title("Extreme Temperature Recorded Every Year")

for item in x.get_ticklabels():
    item.set_rotation(45)
plt.legend(loc='best')

min_x = max(df_high['Date'].min(), df_low['Date'].min())
max_x = min(df_high['Date'].max(), df_low['Date'].max())
xrange = df_low.set_index('Date').index.union(df_high.set_index('Date').index)
lows = df_low.set_index('Date').reindex(xrange).interpolate().loc[min_x:max_x, 'data_value']
highs = df_high.set_index('Date').reindex(xrange).interpolate().loc[min_x:max_x, 'data_value']
ax.fill_between(lows.index, lows, highs, alpha=.4)

Output:

enter image description here

Upvotes: 1

Mr. T
Mr. T

Reputation: 12410

fill_between assumes you have common x-values for both series. If start and end values were the same, you could interpolate as implemented here. However, this is not the case in your example. You could instead create a path object and add it as a filled patch:

import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.path import Path
from matplotlib.patches import PathPatch

fig, ax = plt.subplots(figsize=(15, 10))

#test data generation
highs = pd.DataFrame({'Date': [1, 2, 4, 5], 'Data_Value': [17, 21, 18, 19]})
lows = pd.DataFrame({'Date': [0, 2, 3, 4], 'Data_Value': [1, 3, 2, 3]})

#path object added as patch
p = Path(list(zip(lows['Date'], lows['Data_Value']))[::-1] + list(zip(highs['Date'], highs['Data_Value'])))
patch = PathPatch(p, facecolor="orange", lw=0, alpha=0.2, zorder=-1)
ax.add_patch(patch)

#line graphs plotted on top of the patch
ax.plot(highs['Date'], highs['Data_Value'], label = "Record High", lw=2)
ax.plot(lows['Date'], lows['Data_Value'], label = "Record Low", lw=2)

ax.set_xlabel("Year", fontsize=16)
ax.set_ylabel("Temperature in \N{DEGREE SIGN}C", fontsize=16)
ax.set_title("Extreme Temperature Recorded Every Year")

ax.legend(loc='best')

plt.show()

Sample output: enter image description here

Upvotes: 2

Related Questions