user13079994
user13079994

Reputation: 15

How to smoothen the data into stepped curve?

I have a saved data frame for which I got local maxima and local minima calculated. refer attached picture- data frame plot with local minima and maxima. In this pic, I combined the local minima and maxima column into single and then filled all NAN with zeros hence at zero we see a lot of red dots. below code I used for this purpose:

n=10
df['min'] = df.iloc[argrelextrema(df.data.values, np.less_equal,
                order=n)[0]]['data']
df['max'] = df.iloc[argrelextrema(df.data.values, np.greater_equal,
                order=n)[0]]['data']
df['min'].fillna(0, inplace=True)
df['max'].fillna(0, inplace=True)
df['min_max'] = df['min']+df['max'] 

My objective is to convert this local minima and maxima data into something like a step curve, as shown in this required output.

Also, there is one more issue which is shown in this as pointed by arrows, I have no idea, how to deal with them.

Any hint will be good for me, I can code based on that...

Upvotes: 0

Views: 109

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31226

zero is not correct value for fillna(). It's better as the local minimum or maximum

  • generated a curve off sine curve and randomised it to give it a few features
  • calculated local min/max as per method you have used
  • fillna(method="bfill", limit=n//3) to replicate min / max backwards. Similarly for forwards
  • most graphing libraries (used seaborn) skip nan which is wanted behaviour
import matplotlib.pyplot as plt
from scipy.signal import argrelextrema
import pandas as pd
import numpy as np
import seaborn as sns

# randomize a sine curve a bit...
df = pd.DataFrame(np.sin([a/(2*np.pi) for a in range(180)])*np.random.choice([1,.8,1.2],180, p=(.5,.25,.25)), columns=["data"])

n=10
df['min'] = df.iloc[argrelextrema(df.data.values, np.less_equal,
                order=n)[0]]['data']
df['max'] = df.iloc[argrelextrema(df.data.values, np.greater_equal,
                order=n)[0]]['data']
# combine local minima and maxima
df["min_max"] = np.select([~df["min"].isna(),~df["max"].isna()], [df["min"],df["max"]], np.nan)
# backfill and forward fill for desired outcome on graph...
df["min_max"] = df["min_max"].fillna(method="bfill",limit=n//3).fillna(method="ffill", limit=n//3)

# plot it...
fig, ax = plt.subplots(1,1,figsize=(14, 3))
sns.lineplot(data=df.loc[:,["data","min_max"]], ax=ax)

enter image description here

Upvotes: 1

Related Questions