Object of type Period is not JSON serializable in plotly
Asked Answered
N

2

13

I am trying to plot a line chart. Below is my code

CODE :

import plotly.offline as pyo
import plotly.graph_objects as go
flag = determineFlag('2020-03-01','2020-03-30')

df_r = getDataForTrend(df,'2020-03-01','2020-03-30','d')

colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}



data = [go.Scatter(x = df_r[df_r['S2PName-Category']==category]['S2BillDate'],
                    y = df_r[df_r['S2PName-Category']==category]['totSale'],
                    mode = 'lines',
                    name = category) for category in df_r['S2PName-Category'].unique()]


layout = {'title':'Category Trend',
         'xaxis':{'title':'Time Frame'},
         'yaxis':{'title':'Total Sales Amount','tickformat' : '.2f'}}

fig = go.Figure(data=data,layout=layout)

pyo.iplot(fig)

when I run the above code I get the below error:

ERROR:

TypeError: Object of type Period is not JSON serializable

While tying to debug, I try to execute the below code

DEBUG CODE :

df_r[df_r['S2PName-Category']==category]['S2BillDate']

OP :

3     2020-03-01
11    2020-03-02
21    2020-03-03
26    2020-03-04
41    2020-03-06
42    2020-03-05
46    2020-03-07
Name: S2BillDate, dtype: period[D]

How can I fix the type error ? Is there any tweaks to this ? Any help is much appreciated! Thanks !

Nate answered 7/4, 2020 at 20:22 Comment(3)
Have you tried converting that column of the dataframe to a date instead?Thereby
I did read them as dates , but later I had to perform dot.to-period like this basic_df_2 = basic_df.groupby(['S2PName-Category',basic_df['S2BillDate'].dt.to_period('M')], sort=False)['S2PGTotal'].agg([('totSale','sum')]).reset_index()Nate
Take a look at community.plotly.com/t/…. Since a period encompasses more than one date, you'll have to make a sensible choice about what you want the string representation of the period to be.Hereditary
S
8

AFAIK this is still an issue and plotly will fail in such situation. There is still an open issue at github: Support for Pandas Time spans as index col.

As proposed in the comments one of the solution is to use to_timestatmp conversion, see this.

  1. Create MWE (this is just for reproducibility since there is no data provided in the question)
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.offline as pyo

df = pd.DataFrame({"one": np.random.random(10)}, index=pd.period_range("2020-03-01", freq="M", periods=10))
# Out:
#               one
# 2020-03  0.302359
# 2020-04  0.919923
# 2020-05  0.673808
# 2020-06  0.718974
# 2020-07  0.754675
# 2020-08  0.731673
# 2020-09  0.772382
# 2020-10  0.654555
# 2020-11  0.549314
# 2020-12  0.101696

data = [
    go.Scatter(
        x=df.index,
        y=df["one"],
    )
]
fig = go.Figure(data=data)
pyo.iplot(fig)
# -> will fail ("TypeError: Object of type Period is not JSON serializable")
  1. Use to_timestamp conversion (-> df.index.to_timestamp())
data = [
    go.Scatter(
        x=df.index.to_timestamp(), # period to datetime conversion
        y=df["one"],
    )
]
fig = go.Figure(data=data)
pyo.iplot(fig)

Or, if you do not need datetime format you can convert this to string as well:

data = [
    go.Scatter(
        x=df.index.strftime("%Y-%m"),  # You can define your own format
        y=df["one"],
    )
]
fig = go.Figure(data=data)
pyo.iplot(fig)

You can of course do this conversion right on the original dataframe (so you do not need to do it iteratively inside go.Scatter), but this is just minor stuff. There might be also a way of using custom encoder instead of the default one, but I think it's not worthy of trying and afaik there is no better solution than using one of possible conversion from Period to datetime or string.

Schott answered 10/8, 2021 at 10:23 Comment(0)
S
0

cast the column with .astype('str')

Credits to: https://mcmap.net/q/907942/-typeerror-object-of-type-interval-is-not-json-serializable-in-plotly-python

Stripe answered 13/3 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.