skidjoe
skidjoe

Reputation: 649

Anyway to smooth a plotly line chart?

I have a number of plots which I'm trying to plot as a smooth curve instead of a line plot with markers that are volatile, is there any option to do this? Below is an example dictionary which represents one of the plots, I'm then converting that dict into a DataFrame and throwing it in to plotly. The thing is, the plot doesn't look clean (it fluctuates a lot), I want something that smoothes it out, is there an option to do that?

    uncert = {0.01: 0.3132940811899597,
     0.03: 0.3654332700822265,
     0.05: 0.26783984501130126,
     0.07: 0.4321293089229754,
     0.09: 0.25012641159615706,
     0.11: 0.3714236470182696,
     0.13: 0.38346262341325815,
     0.15: 0.35005413208228076,
     0.17: 0.5588615782664942,
     0.19: 0.5836015906078394,
     0.21: 0.5266019417475728,
     0.23: 0.6645418326693228,
     0.25: 0.6699386503067485,
     0.27: 0.6684177348182391,
     0.29: 0.711600777705768,
     0.31: 0.7152067585593596,
     0.33: 0.6994047619047619,
     0.35: 0.6908919301557338,
     0.37: 0.7428780131482835,
     0.39: 0.6894644204174001,
     0.41: 0.7527301092043682,
     0.43: 0.816200215285253,
     0.45: 0.8000557724484105,
     0.47: 0.7623733719247467,
     0.49: 0.843609022556391,
     0.5: 0.7963190184049078,
     0.52: 0.8063279002876317,
     0.54: 0.8296098699566522,
     0.56: 0.8319386331938632,
     0.58: 0.7823228634039445,
     0.6: 0.7898773006134969,
     0.62: 0.8312474767864352,
     0.64: 0.8414997869620793,
     0.66: 0.8583032490974728,
     0.68: 0.8475551294343241,
     0.7: 0.8271983640081799,
     0.72: 0.8509589041095891,
     0.74: 0.848377581120944} 


plot = pd.DataFrame({"uncert":uncert})
fig = px.line(plot, x='% data', y=plot.columns[1:], markers=True, title="")

Upvotes: 1

Views: 3691

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31146

from scipy import signal
import pandas as pd
import plotly.express as px
import statsmodels.api as sm

uncert = {
    0.01: 0.3132940811899597,
    0.03: 0.3654332700822265,
    0.05: 0.26783984501130126,
    0.07: 0.4321293089229754,
    0.09: 0.25012641159615706,
    0.11: 0.3714236470182696,
    0.13: 0.38346262341325815,
    0.15: 0.35005413208228076,
    0.17: 0.5588615782664942,
    0.19: 0.5836015906078394,
    0.21: 0.5266019417475728,
    0.23: 0.6645418326693228,
    0.25: 0.6699386503067485,
    0.27: 0.6684177348182391,
    0.29: 0.711600777705768,
    0.31: 0.7152067585593596,
    0.33: 0.6994047619047619,
    0.35: 0.6908919301557338,
    0.37: 0.7428780131482835,
    0.39: 0.6894644204174001,
    0.41: 0.7527301092043682,
    0.43: 0.816200215285253,
    0.45: 0.8000557724484105,
    0.47: 0.7623733719247467,
    0.49: 0.843609022556391,
    0.5: 0.7963190184049078,
    0.52: 0.8063279002876317,
    0.54: 0.8296098699566522,
    0.56: 0.8319386331938632,
    0.58: 0.7823228634039445,
    0.6: 0.7898773006134969,
    0.62: 0.8312474767864352,
    0.64: 0.8414997869620793,
    0.66: 0.8583032490974728,
    0.68: 0.8475551294343241,
    0.7: 0.8271983640081799,
    0.72: 0.8509589041095891,
    0.74: 0.848377581120944,
}


plot = pd.DataFrame({"uncert": uncert})
fig = (
    px.line(plot, y="uncert", markers=True, title="")
    .update_traces(name="original")
    .add_traces(
        px.line(
            plot,
            y=signal.savgol_filter(
                plot["uncert"], 11, 3
            ),  # window size used for filtering
            markers=True,
        )
        .update_traces(name="savgol")
        .data
    )
    .add_traces(
        px.line(
            plot,
            y=sm.nonparametric.lowess(plot["uncert"], plot.index, frac=0.3)[
                :, 1
            ],  # window size used for filtering
            markers=True,
        )
        .update_traces(name="lowres")
        .data
    )
    .update_traces(showlegend=True, line_color=None)
)

fig

enter image description here

Upvotes: 2

Related Questions