codeheadache
codeheadache

Reputation: 164

how to perform conditional area plotting with matplotlib?

I have created the following dataframe based on a range of data.

df['data_classification'] = df.myDatarange.apply(lambda a:'Very good' if a>=-90 
                                       else ('Good' if (a>= -100 or a<=-91) 
                                             else ('Moderate' if (a>= -110 or a<=-101) 
                                                   else ('Poor' if (a>= -123 or a<=-111) 
                                                         else ('Bad' if (a>= -140 or a<=-124) 
                                                               else 'Off' )))))

I am planning to plot myDatarange with data_classification and somehow show the relation with different colour. I am very confused how to plot this. I can plot myDatarange as a single lineplot, but how to relate the two data?

So far, I have tried the following:

x1 = df1.index
y1 = df1.myDatarange
f, (ax1,ax2) = plt.subplots(2,figsize=(5, 5))
ax1.plot(x1,y1,color='red', linewidth=1.9, alpha=0.9, label="myDataRange")
plt.show()

How can I plot the above range of data based on classification as area plot? Is there a better way than area plot to express my data? There are examples on the net, but not very clear on conditional side of it.

Upvotes: 0

Views: 804

Answers (1)

JohanC
JohanC

Reputation: 80349

Seaborn's barplot can take a hue parameter to color each bar corresponding to the 'data_classification'. The new 'data_classification' column can be created quicker and easier to modify via pd.cut.

The barplot can be used as background for the lineplot to show the classification of each value.

Here is an example to get you started:

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

df = pd.DataFrame({'myDatarange': np.random.randint(-150, -50, size=50)})
ranges = [-10**6, -140, -123, -110, -100, -90, 10**6]
df['data_classification'] = pd.cut(df['myDatarange'], ranges, right=False,
                                   labels=['Off', 'Bad', 'Poor', 'Moderate', 'Good', 'Very Good'])

fig, ax1 = plt.subplots(figsize=(12, 4))
ax1.plot(df.index, df['myDatarange'], color='blue', linewidth=2, alpha=0.9, label="myDataRange")

sns.barplot(x=df.index, y=[df['myDatarange'].min()] * len(df),
            hue='data_classification', alpha=0.5, palette='inferno', dodge=False, data=df, ax=ax1)
for bar in ax1.patches: # optionally set the bars to fill the complete background, default seaborn sets the width to about 80%
    bar.set_width(1)

plt.legend(bbox_to_anchor=(1.02, 1.05) , loc='upper left')
plt.tight_layout()
plt.show()

example plot

PS: If you want to the 0 at the bottom (now at the top due to the negative y-values), you could call ax.invert_yaxis().

Upvotes: 2

Related Questions