Skip to content

Commit eed299f

Browse files
authored
BUG: Resampler.ohlc with empty data (#53272)
1 parent 48690d4 commit eed299f

File tree

3 files changed

+41
-12
lines changed

3 files changed

+41
-12
lines changed

doc/source/whatsnew/v2.1.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,11 @@ Groupby/resample/rolling
506506
- Bug in :meth:`GroupBy.groups` with a datetime key in conjunction with another key produced incorrect number of group keys (:issue:`51158`)
507507
- Bug in :meth:`GroupBy.quantile` may implicitly sort the result index with ``sort=False`` (:issue:`53009`)
508508
- Bug in :meth:`GroupBy.var` failing to raise ``TypeError`` when called with datetime64, timedelta64 or :class:`PeriodDtype` values (:issue:`52128`, :issue:`53045`)
509+
- Bug in :meth:`Resampler.ohlc` with empty object returning a :class:`Series` instead of empty :class:`DataFrame` (:issue:`42902`)
509510
- Bug in :meth:`SeriesGroupBy.nth` and :meth:`DataFrameGroupBy.nth` after performing column selection when using ``dropna="any"`` or ``dropna="all"`` would not subset columns (:issue:`53518`)
510511
- Bug in :meth:`SeriesGroupBy.nth` and :meth:`DataFrameGroupBy.nth` raised after performing column selection when using ``dropna="any"`` or ``dropna="all"`` resulted in rows being dropped (:issue:`53518`)
511512
- Bug in :meth:`SeriesGroupBy.sum` and :meth:`DataFrameGroupby.sum` summing ``np.inf + np.inf`` and ``(-np.inf) + (-np.inf)`` to ``np.nan`` (:issue:`53606`)
513+
-
512514

513515
Reshaping
514516
^^^^^^^^^

pandas/core/resample.py

+18
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
)
6363
from pandas.core.groupby.grouper import Grouper
6464
from pandas.core.groupby.ops import BinGrouper
65+
from pandas.core.indexes.api import MultiIndex
6566
from pandas.core.indexes.datetimes import (
6667
DatetimeIndex,
6768
date_range,
@@ -1460,6 +1461,23 @@ def ohlc(
14601461
):
14611462
maybe_warn_args_and_kwargs(type(self), "ohlc", args, kwargs)
14621463
nv.validate_resampler_func("ohlc", args, kwargs)
1464+
1465+
ax = self.ax
1466+
obj = self._obj_with_exclusions
1467+
if len(ax) == 0:
1468+
# GH#42902
1469+
obj = obj.copy()
1470+
obj.index = _asfreq_compat(obj.index, self.freq)
1471+
if obj.ndim == 1:
1472+
obj = obj.to_frame()
1473+
obj = obj.reindex(["open", "high", "low", "close"], axis=1)
1474+
else:
1475+
mi = MultiIndex.from_product(
1476+
[obj.columns, ["open", "high", "low", "close"]]
1477+
)
1478+
obj = obj.reindex(mi, axis=1)
1479+
return obj
1480+
14631481
return self._downsample("ohlc")
14641482

14651483
@doc(SeriesGroupBy.nunique)

pandas/tests/resample/test_base.py

+21-12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from pandas import (
77
DataFrame,
8+
MultiIndex,
89
NaT,
910
PeriodIndex,
1011
Series,
@@ -100,16 +101,9 @@ def test_raises_on_non_datetimelike_index():
100101

101102
@all_ts
102103
@pytest.mark.parametrize("freq", ["M", "D", "H"])
103-
def test_resample_empty_series(freq, empty_series_dti, resample_method, request):
104+
def test_resample_empty_series(freq, empty_series_dti, resample_method):
104105
# GH12771 & GH12868
105106

106-
if resample_method == "ohlc" and isinstance(empty_series_dti.index, PeriodIndex):
107-
request.node.add_marker(
108-
pytest.mark.xfail(
109-
reason=f"GH13083: {resample_method} fails for PeriodIndex"
110-
)
111-
)
112-
113107
ser = empty_series_dti
114108
if freq == "M" and isinstance(ser.index, TimedeltaIndex):
115109
msg = (
@@ -123,12 +117,19 @@ def test_resample_empty_series(freq, empty_series_dti, resample_method, request)
123117
rs = ser.resample(freq)
124118
result = getattr(rs, resample_method)()
125119

126-
expected = ser.copy()
127-
expected.index = _asfreq_compat(ser.index, freq)
120+
if resample_method == "ohlc":
121+
expected = DataFrame(
122+
[], index=ser.index[:0].copy(), columns=["open", "high", "low", "close"]
123+
)
124+
expected.index = _asfreq_compat(ser.index, freq)
125+
tm.assert_frame_equal(result, expected, check_dtype=False)
126+
else:
127+
expected = ser.copy()
128+
expected.index = _asfreq_compat(ser.index, freq)
129+
tm.assert_series_equal(result, expected, check_dtype=False)
128130

129131
tm.assert_index_equal(result.index, expected.index)
130132
assert result.index.freq == expected.index.freq
131-
tm.assert_series_equal(result, expected, check_dtype=False)
132133

133134

134135
@all_ts
@@ -203,7 +204,15 @@ def test_resample_empty_dataframe(empty_frame_dti, freq, resample_method):
203204

204205
rs = df.resample(freq, group_keys=False)
205206
result = getattr(rs, resample_method)()
206-
if resample_method != "size":
207+
if resample_method == "ohlc":
208+
# TODO: no tests with len(df.columns) > 0
209+
mi = MultiIndex.from_product([df.columns, ["open", "high", "low", "close"]])
210+
expected = DataFrame(
211+
[], index=df.index[:0].copy(), columns=mi, dtype=np.float64
212+
)
213+
expected.index = _asfreq_compat(df.index, freq)
214+
215+
elif resample_method != "size":
207216
expected = df.copy()
208217
else:
209218
# GH14962

0 commit comments

Comments
 (0)