Skip to content

Commit 2d8f0ed

Browse files
committed
timeseries_json_to_pandas: allow timeseries as JSON dump or path
1 parent 0040d60 commit 2d8f0ed

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
### Changed
1616

1717
- Harden STAC parsing of "bands"/"eo:bands" when "name" field is not present (which is technically not a required field) ([#860](https://github.com/Open-EO/openeo-python-client/issues/860))
18+
- `openeo.rest.conversions.timeseries_json_to_pandas`: allow timeseries to be given as a raw JSON dump or path to JSON file.
1819

1920
### Removed
2021

openeo/rest/conversions.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
from __future__ import annotations
66

77
import typing
8+
from pathlib import Path
9+
from typing import Union
810

911
import numpy as np
1012
import pandas
1113

1214
from openeo.internal.warnings import deprecated
15+
from openeo.util import load_json_resource
1316

1417
if typing.TYPE_CHECKING:
1518
# Imports for type checking only (circular import issue at runtime).
@@ -22,7 +25,9 @@ class InvalidTimeSeriesException(ValueError):
2225
pass
2326

2427

25-
def timeseries_json_to_pandas(timeseries: dict, index: str = "date", auto_collapse=True) -> pandas.DataFrame:
28+
def timeseries_json_to_pandas(
29+
timeseries: Union[dict, str, Path], index: str = "date", auto_collapse=True
30+
) -> pandas.DataFrame:
2631
"""
2732
Convert a timeseries JSON object as returned by the `aggregate_spatial` process to a pandas DataFrame object
2833
@@ -32,16 +37,21 @@ def timeseries_json_to_pandas(timeseries: dict, index: str = "date", auto_collap
3237
When there is just a single polygon or band in play, the dataframe will be simplified
3338
by removing the corresponding dimension if `auto_collapse` is enabled (on by default).
3439
35-
:param timeseries: dictionary as returned by `aggregate_spatial`
40+
:param timeseries: dictionary, JSON dump, or path to JSON file as returned by `aggregate_spatial`
3641
:param index: which dimension should be used for the DataFrame index: 'date' or 'polygon'
3742
:param auto_collapse: whether single band or single polygon cases should be simplified automatically
3843
3944
:return: pandas DataFrame or Series
45+
46+
.. versionchanged:: 0.48.0
47+
The `timeseries` argument to also be a JSON dump or a path to a JSON file, in addition to a dictionary.
4048
"""
4149
# The input timeseries dictionary is assumed to have this structure:
4250
# {dict mapping date -> [list with one item per polygon: [list with one float/None per band or empty list]]}
4351
# TODO is this format of `aggregate_spatial` standardized across backends? Or can we detect the structure?
44-
# TODO: option to pass a path to a JSON file as input?
52+
53+
if not isinstance(timeseries, dict):
54+
timeseries = load_json_resource(timeseries)
4555

4656
# Some quick checks
4757
if len(timeseries) == 0:

tests/rest/test_conversions.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from pathlib import Path
2+
13
import numpy as np
24
import pandas as pd
35
import pytest
@@ -26,10 +28,34 @@ def test_timeseries_json_to_pandas_basic():
2628
[7, 8, 9, 10, 11, 12]
2729
],
2830
index=pd.Index([DATE1, DATE2], name="date"),
29-
columns=pd.MultiIndex.from_tuples(
30-
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)],
31-
names=("polygon", "band")
32-
)
31+
columns=pd.MultiIndex.from_tuples([(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)], names=("polygon", "band")),
32+
)
33+
assert_frame_equal(df, expected)
34+
35+
36+
@pytest.mark.parametrize(["path_factory"], [(str,), (Path,)])
37+
def test_test_timeseries_json_to_pandas_from_file(tmp_path, path_factory):
38+
path = tmp_path / "timeseries.json"
39+
path.write_text(""" {"2019-01-11T11:11:11Z": [[1, 2], [33, 44]]} """)
40+
41+
timeseries = path_factory(path)
42+
43+
df = timeseries_json_to_pandas(timeseries)
44+
expected = pd.DataFrame(
45+
data=[[1, 2, 33, 44]],
46+
index=pd.Index(["2019-01-11T11:11:11Z"], name="date"),
47+
columns=pd.MultiIndex.from_tuples([(0, 0), (0, 1), (1, 0), (1, 1)], names=("polygon", "band")),
48+
)
49+
assert_frame_equal(df, expected)
50+
51+
52+
def test_test_timeseries_json_to_pandas_from_json_dump():
53+
timeseries = """ {"2019-01-11T11:11:11Z": [[1, 2], [33, 44]]} """
54+
df = timeseries_json_to_pandas(timeseries)
55+
expected = pd.DataFrame(
56+
data=[[1, 2, 33, 44]],
57+
index=pd.Index(["2019-01-11T11:11:11Z"], name="date"),
58+
columns=pd.MultiIndex.from_tuples([(0, 0), (0, 1), (1, 0), (1, 1)], names=("polygon", "band")),
3359
)
3460
assert_frame_equal(df, expected)
3561

0 commit comments

Comments
 (0)