Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dataframe (de)serialization #600

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
7 changes: 4 additions & 3 deletions param/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import re
import datetime as dt
import collections
import json

from .parameterized import ( Undefined,
Parameterized, Parameter, String, ParameterizedFunction, ParamOverrides,
Expand Down Expand Up @@ -1657,14 +1658,14 @@ def _validate(self, val):
def serialize(cls, value):
if value is None:
return None
return value.to_dict('records')
return json.loads(value.to_json(date_format='iso'))

@classmethod
def deserialize(cls, value):
if value == 'null' or value is None:
return None
from pandas import DataFrame as pdDFrame
return pdDFrame(value)
import pandas as pd
return pd.read_json(json.dumps(value))


class Series(ClassSelector):
Expand Down
20 changes: 17 additions & 3 deletions tests/API1/testjsonserialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class TestSet(param.Parameterized):
__test__ = False

numpy_params = ['r','y']
pandas_params = ['s','t','u','z']
pandas_params = ['s','t','u','z','ag','ah']
conditionally_unsafe = ['f', 'o']

a = param.Integer(default=5, doc='Example doc', bounds=(2,30), inclusive_bounds=(True, False))
Expand Down Expand Up @@ -101,7 +101,12 @@ class TestSet(param.Parameterized):
# datetime.datetime comparison with numpy.datetime64 fails on Python 2
ae = None if (np is None or on_py2) else param.DateRange(default=(npdt1, npdt2))
af = None if pd is None else param.DateRange(default=(pdts1, pdts2))

ag = None if pd is None else param.DataFrame(default=pd.DataFrame(
{'A':[datetime.datetime(year,1,1) for year in range(2020,2023)], 'B':[1.1,2.2,3.3]}),
columns=(1,4), rows=(2,5))
ah = None if pd is None else param.DataFrame(default=pd.DataFrame(
[[1,2,3],[4,5,6],[7,8,9]]),
columns=(1,4), rows=(2,5))

test = TestSet(a=29)

Expand Down Expand Up @@ -232,13 +237,22 @@ def test_numpy_instance_serialization(self):

@pd_skip
def test_pandas_instance_serialization(self):
from pandas.api.types import is_datetime64_any_dtype as is_datetime
serialized = test.param.serialize_parameters(subset=test.pandas_params, mode=self.mode)
deserialized = TestSet.param.deserialize_parameters(serialized, mode=self.mode)
for pname in test.pandas_params:
if getattr(test, pname) is None:
self.assertTrue(deserialized[pname] is None)
else:
self.assertTrue(getattr(test, pname).equals(deserialized[pname]))
test_df = getattr(test, pname)
deser_df = deserialized[pname].copy()

date_cols = [c for c in test_df.columns if is_datetime(test_df[c])]
for c in date_cols:
deser_df[c] = pd.to_datetime(deser_df[c])

pd.testing.assert_frame_equal(test_df, deser_df)


def test_serialize_calendar_date_range_class(self):
self._test_serialize(TestSet, 'ab')
Expand Down