1

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

Hardik Dhuri
  • 363
  • 1
  • 2
  • 8

2 Answers2

2

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

Mr. T
  • 11,960
  • 10
  • 32
  • 54
  • TypeError: float() argument must be a string or a number, not 'Timestamp'. I got this error at the declaration of 'p' – Hardik Dhuri Feb 10 '21 at 04:57
  • Happens if the question doesn't provide a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Mr. T Feb 10 '21 at 09:25
1

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

Scott Boston
  • 147,308
  • 15
  • 139
  • 187
  • 1
    Ah, good point. I did not consider that this might be the intended output of filling the area between the curves. – Mr. T Feb 09 '21 at 19:36
  • If this answer solved your problem, you [should accept it](https://stackoverflow.com/help/someone-answers). – Mr. T Feb 10 '21 at 09:28