rpb
rpb

Reputation: 3299

Overlay Shaded Regions on a Line Plot Based on Conditions

I would like to plot a line plot and make different overlay based on condition as illustrated below.

enter image description here

May I know how, or if possible, please kindly redirect me to right material on achieving the intended objective.

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
np.random.seed(0)
rng = np.random.default_rng(2)
mlist=[]
for _ in range(4):

    m=np.random.rand(4).tolist()
    n=rng.integers(0, 6, size=(1)).tolist()*4
    df = pd.DataFrame(zip(m,n), columns=['yval','type'])
    mlist.append(df)

df=pd.concat(mlist).reset_index(drop=True).reset_index()
sns.lineplot(data=df, x="index", y="yval")
plt.show()

Suggestion using Matplotlib or Seaborn, or any other package are welcome

Upvotes: 1

Views: 444

Answers (2)

r-beginners
r-beginners

Reputation: 35155

The filling of the section was achieved using axvspan. I also used text for annotations.

The line is plotted with sns.lineplot, but can also be implemented with either of the following:

  • ax = df.plot(y='yval')
  • fig, ax = plt.subplots() and ax.plot('index', 'yval', data=df)
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# Create Sample Data
np.random.seed(0)
rng = np.random.default_rng(2)

m = np.random.rand(16)
n = np.repeat(rng.integers(0, 6, size=4), 4)
df = pd.DataFrame({'index': range(len(m)), 'yval': m, 'type': n})

# Plot the line
ax = sns.lineplot(data=df, x="index", y="yval")

# Add the overlay spans and annotations
overlay = {0: 'm', 1: 'gray', 5: 'r'}

for i in np.arange(0, len(df), 4):
    tmp = df.iloc[i:i+4, :]
    v = overlay.get(tmp.type.unique()[0])
    ax.axvspan(min(tmp.index), max(tmp.index)+1, color=v, alpha=0.3)
    ax.text(((min(tmp.index)+max(tmp.index)+1) / 2)-1, 0.1, f'type {tmp.type.unique()[0]}', fontsize=12)

plt.show()

enter image description here

Upvotes: 2

rpb
rpb

Reputation: 3299

Using Matplotlib add_patch and text

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.patches as patches

import matplotlib.colors as mcolors
# nn=mcolors.CSS4_COLORS
all_colors=list(mcolors.TABLEAU_COLORS.keys())

b=1
np.random.seed(0)
rng = np.random.default_rng(2)
mlist=[]
for _ in range(4):

    m=np.random.rand(4).tolist()
    n=rng.integers(0, 6, size=(1)).tolist()*4
    df = pd.DataFrame(zip(m,n), columns=['yval','type'])
    mlist.append(df)

df=pd.concat(mlist).reset_index(drop=True).reset_index()
# df.to_feather('test.feather')
# df=pd.read_feather('test.feather')
df['C'] = df['type'].diff()
df['C']=df['C'].fillna(10)

nb=df.type[(df['C'] != 0)].to_frame().reset_index()
unique_val=nb['type'].drop_duplicates().sort_values().tolist()
ngroup_type=dict(zip(unique_val,[f'type {idx}' for idx in unique_val]))
nb['ngroup']=nb["type"].map(ngroup_type)
color_group=all_colors[:len(unique_val)]
res = dict(zip(unique_val, color_group))
nb["color"] = nb["type"].map(res)


starting_point=nb["index"].values.tolist()
mcolor=nb["color"].values.tolist()
group_type=nb["ngroup"].values.tolist()
nspace=4
nheight=1
fg=sns.lineplot(data=df, x="index", y="yval")
for ncolor,spoint,gtype in zip(mcolor,starting_point,group_type):
    fg.axes.add_patch(patches.Rectangle((spoint, 0),
            nspace,nheight,edgecolor = 'blue',
                                   facecolor = ncolor,fill=True,alpha=0.1,ls=':') )
    fg.axes.text(spoint+1.5, 0.1, gtype , size=10,
         va="baseline", ha="left", multialignment="left")
plt.show()

Upvotes: 0

Related Questions