Skip to content

Creating a timeline does not work with [new] pandas 2.0.0 #4102

Closed
@kaibir

Description

@kaibir

Description:

When test-driving the new pandas release candidate 2.0.0rc0 we noticed that generating Plotly graphs failed (snippet for reference below).

When investigating, we found the following in the Plotly code: (x_end - x_start).astype("timedelta64[ms]"). With Pandas < 2 this returned float64 representing the ms between the timestamps.

Now that Pandas 2 has a timedelta64[ms] dtype this dtype is used instead.

import pandas as pd

x_start = pd.Series(pd.Timestamp(2023,3,14,12))
x_end = pd.Series(pd.Timestamp(2023,3,14,14))

# Pandas 1.5.3
# 0    7200000.0
# dtype: float64
# 
# Pandas 2.0.0rc0
# 0   0 days 02:00:00
# dtype: timedelta64[ms]
(x_end - x_start).astype("timedelta64[ms]")

But Plotly expects a float64 dtype and we run into an issue, that timedelta is not JSON serializable (see Plotly reproduction below)

The following works with all Pandas versions (especially 1.5.3 and 2.0.0rc0):

(x_end - x_start).astype("timedelta64[ns]") / pd.Timedelta(1, 'ms')`

Plotly reproduction (with pandas 2.0.0rc0

import plotly.express as px
import pandas as pd

df = pd.DataFrame([{"Task": "Job A", "Start": "2022-01-01", "Finish": "2022-01-02"}])
fig_1 = px.timeline(df, x_start="Start", x_end="Finish", y="Task")
fig_1.update_yaxes(autorange="reversed")

leads to

[...]
File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/encoder.py:258, in JSONEncoder.iterencode(self, o, _one_shot)
    253 else:
    254     _iterencode = _make_iterencode(
    255         markers, self.default, _encoder, self.indent, floatstr,
    256         self.key_separator, self.item_separator, self.sort_keys,
    257         self.skipkeys, _one_shot)
--> 258 return _iterencode(o, 0)

File ~/venv/weplan3.11/lib/python3.11/site-packages/_plotly_utils/utils.py:136, in PlotlyJSONEncoder.default(self, obj)
    134     except NotEncodable:
    135         pass
--> 136 return _json.JSONEncoder.default(self, obj)

File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/encoder.py:180, in JSONEncoder.default(self, o)
    161 def default(self, o):
    162     """Implement this method in a subclass such that it returns
    163     a serializable object for ``o``, or calls the base implementation
    164     (to raise a ``TypeError``).
   (...)
    178 
    179     """
--> 180     raise TypeError(f'Object of type {o.__class__.__name__} '
    181                     f'is not JSON serializable')

TypeError: Object of type timedelta is not JSON serializable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions