diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 3b04d9937d7f2..3404bcede4e54 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -179,6 +179,7 @@ Other Enhancements - :class:`IntervalIndex` has gained the :meth:`~IntervalIndex.set_closed` method to change the existing ``closed`` value (:issue:`21670`) - :func:`~DataFrame.to_csv` and :func:`~DataFrame.to_json` now support ``compression='infer'`` to infer compression based on filename (:issue:`15008`) - :func:`to_timedelta` now supports iso-formated timedelta strings (:issue:`21877`) +- :func:`read_json` now parses timedelta with `orient='table'` (:issue:`21140`) - :class:`Series` and :class:`DataFrame` now support :class:`Iterable` in constructor (:issue:`2193`) .. _whatsnew_0240.api_breaking: diff --git a/pandas/io/json/table_schema.py b/pandas/io/json/table_schema.py index 2dc176648fb31..78ce7c7a00224 100644 --- a/pandas/io/json/table_schema.py +++ b/pandas/io/json/table_schema.py @@ -6,7 +6,7 @@ import warnings import pandas._libs.json as json -from pandas import DataFrame +from pandas import DataFrame, to_timedelta from pandas.api.types import CategoricalDtype import pandas.core.common as com from pandas.core.dtypes.common import ( @@ -163,7 +163,7 @@ def convert_json_field_to_pandas_type(field): elif typ == 'boolean': return 'bool' elif typ == 'duration': - return 'timedelta64' + return 'timedelta64[ns]' elif typ == 'datetime': if field.get('tz'): return 'datetime64[ns, {tz}]'.format(tz=field['tz']) @@ -306,10 +306,9 @@ def parse_table_schema(json, precise_float): raise NotImplementedError('table="orient" can not yet read timezone ' 'data') - # No ISO constructor for Timedelta as of yet, so need to raise - if 'timedelta64' in dtypes.values(): - raise NotImplementedError('table="orient" can not yet read ' - 'ISO-formatted Timedelta data') + for col, dtype in dtypes.items(): + if dtype == 'timedelta64[ns]': + df[col] = to_timedelta(df[col]) df = df.astype(dtypes) diff --git a/pandas/tests/io/json/test_json_table_schema.py b/pandas/tests/io/json/test_json_table_schema.py index b6483d0e978ba..10ce834b08873 100644 --- a/pandas/tests/io/json/test_json_table_schema.py +++ b/pandas/tests/io/json/test_json_table_schema.py @@ -390,7 +390,7 @@ def test_convert_pandas_type_to_json_field_categorical(self, kind, ({'type': 'integer'}, 'int64'), ({'type': 'number'}, 'float64'), ({'type': 'boolean'}, 'bool'), - ({'type': 'duration'}, 'timedelta64'), + ({'type': 'duration'}, 'timedelta64[ns]'), ({'type': 'datetime'}, 'datetime64[ns]'), ({'type': 'datetime', 'tz': 'US/Hawaii'}, 'datetime64[ns, US/Hawaii]'), ({'type': 'any'}, 'object'), @@ -499,6 +499,7 @@ class TestTableOrientReader(object): 'level_0']) @pytest.mark.parametrize("vals", [ {'ints': [1, 2, 3, 4]}, + {'timedeltas': pd.timedelta_range('1H', periods=4, freq='T')}, {'objects': ['a', 'b', 'c', 'd']}, {'date_ranges': pd.date_range('2016-01-01', freq='d', periods=4)}, {'categoricals': pd.Series(pd.Categorical(['a', 'b', 'c', 'c']))}, @@ -516,7 +517,6 @@ def test_read_json_table_orient(self, index_nm, vals, recwarn): @pytest.mark.parametrize("index_nm", [ None, "idx", "index"]) @pytest.mark.parametrize("vals", [ - {'timedeltas': pd.timedelta_range('1H', periods=4, freq='T')}, {'timezones': pd.date_range('2016-01-01', freq='d', periods=4, tz='US/Central')}]) def test_read_json_table_orient_raises(self, index_nm, vals, recwarn): @@ -530,7 +530,7 @@ def test_comprehensive(self): {'A': [1, 2, 3, 4], 'B': ['a', 'b', 'c', 'c'], 'C': pd.date_range('2016-01-01', freq='d', periods=4), - # 'D': pd.timedelta_range('1H', periods=4, freq='T'), + 'D': pd.timedelta_range('1H', periods=4, freq='T'), 'E': pd.Series(pd.Categorical(['a', 'b', 'c', 'c'])), 'F': pd.Series(pd.Categorical(['a', 'b', 'c', 'c'], ordered=True)),