Skip to content

Commit 891b16f

Browse files
authored
TST/REF: share method tests between DataFrame and Series (#37596)
1 parent d2bc94a commit 891b16f

13 files changed

+318
-395
lines changed

pandas/conftest.py

+10
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,16 @@ def unique_nulls_fixture(request):
290290
# ----------------------------------------------------------------
291291
# Classes
292292
# ----------------------------------------------------------------
293+
294+
295+
@pytest.fixture(params=[pd.DataFrame, pd.Series])
296+
def frame_or_series(request):
297+
"""
298+
Fixture to parametrize over DataFrame and Series.
299+
"""
300+
return request.param
301+
302+
293303
@pytest.fixture(
294304
params=[pd.Index, pd.Series], ids=["index", "series"] # type: ignore[list-item]
295305
)

pandas/core/frame.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,13 @@
131131
from pandas.core.construction import extract_array
132132
from pandas.core.generic import NDFrame, _shared_docs
133133
from pandas.core.indexes import base as ibase
134-
from pandas.core.indexes.api import Index, ensure_index, ensure_index_from_sequences
134+
from pandas.core.indexes.api import (
135+
DatetimeIndex,
136+
Index,
137+
PeriodIndex,
138+
ensure_index,
139+
ensure_index_from_sequences,
140+
)
135141
from pandas.core.indexes.multi import MultiIndex, maybe_droplevels
136142
from pandas.core.indexing import check_bool_indexer, convert_to_index_sliceable
137143
from pandas.core.internals import BlockManager
@@ -9253,6 +9259,9 @@ def to_timestamp(
92539259

92549260
axis_name = self._get_axis_name(axis)
92559261
old_ax = getattr(self, axis_name)
9262+
if not isinstance(old_ax, PeriodIndex):
9263+
raise TypeError(f"unsupported Type {type(old_ax).__name__}")
9264+
92569265
new_ax = old_ax.to_timestamp(freq=freq, how=how)
92579266

92589267
setattr(new_obj, axis_name, new_ax)
@@ -9282,6 +9291,9 @@ def to_period(self, freq=None, axis: Axis = 0, copy: bool = True) -> DataFrame:
92829291

92839292
axis_name = self._get_axis_name(axis)
92849293
old_ax = getattr(self, axis_name)
9294+
if not isinstance(old_ax, DatetimeIndex):
9295+
raise TypeError(f"unsupported Type {type(old_ax).__name__}")
9296+
92859297
new_ax = old_ax.to_period(freq=freq)
92869298

92879299
setattr(new_obj, axis_name, new_ax)

pandas/tests/frame/methods/test_at_time.py

+33-12
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,57 @@
44
import pytest
55
import pytz
66

7+
from pandas._libs.tslibs import timezones
8+
79
from pandas import DataFrame, date_range
810
import pandas._testing as tm
911

1012

1113
class TestAtTime:
12-
def test_at_time(self):
14+
@pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"])
15+
def test_localized_at_time(self, tzstr, frame_or_series):
16+
tz = timezones.maybe_get_tz(tzstr)
17+
18+
rng = date_range("4/16/2012", "5/1/2012", freq="H")
19+
ts = frame_or_series(np.random.randn(len(rng)), index=rng)
20+
21+
ts_local = ts.tz_localize(tzstr)
22+
23+
result = ts_local.at_time(time(10, 0))
24+
expected = ts.at_time(time(10, 0)).tz_localize(tzstr)
25+
tm.assert_equal(result, expected)
26+
assert timezones.tz_compare(result.index.tz, tz)
27+
28+
def test_at_time(self, frame_or_series):
1329
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
1430
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)
31+
if frame_or_series is not DataFrame:
32+
ts = ts[0]
1533
rs = ts.at_time(rng[1])
1634
assert (rs.index.hour == rng[1].hour).all()
1735
assert (rs.index.minute == rng[1].minute).all()
1836
assert (rs.index.second == rng[1].second).all()
1937

2038
result = ts.at_time("9:30")
2139
expected = ts.at_time(time(9, 30))
22-
tm.assert_frame_equal(result, expected)
23-
24-
result = ts.loc[time(9, 30)]
25-
expected = ts.loc[(rng.hour == 9) & (rng.minute == 30)]
26-
27-
tm.assert_frame_equal(result, expected)
40+
tm.assert_equal(result, expected)
2841

42+
def test_at_time_midnight(self, frame_or_series):
2943
# midnight, everything
3044
rng = date_range("1/1/2000", "1/31/2000")
3145
ts = DataFrame(np.random.randn(len(rng), 3), index=rng)
46+
if frame_or_series is not DataFrame:
47+
ts = ts[0]
3248

3349
result = ts.at_time(time(0, 0))
34-
tm.assert_frame_equal(result, ts)
50+
tm.assert_equal(result, ts)
3551

52+
def test_at_time_nonexistent(self, frame_or_series):
3653
# time doesn't exist
3754
rng = date_range("1/1/2012", freq="23Min", periods=384)
38-
ts = DataFrame(np.random.randn(len(rng), 2), rng)
55+
ts = DataFrame(np.random.randn(len(rng)), rng)
56+
if frame_or_series is not DataFrame:
57+
ts = ts[0]
3958
rs = ts.at_time("16:00")
4059
assert len(rs) == 0
4160

@@ -62,12 +81,14 @@ def test_at_time_tz(self):
6281
expected = df.iloc[1:2]
6382
tm.assert_frame_equal(result, expected)
6483

65-
def test_at_time_raises(self):
84+
def test_at_time_raises(self, frame_or_series):
6685
# GH#20725
67-
df = DataFrame([[1, 2, 3], [4, 5, 6]])
86+
obj = DataFrame([[1, 2, 3], [4, 5, 6]])
87+
if frame_or_series is not DataFrame:
88+
obj = obj[0]
6889
msg = "Index must be DatetimeIndex"
6990
with pytest.raises(TypeError, match=msg): # index is not a DatetimeIndex
70-
df.at_time("00:00")
91+
obj.at_time("00:00")
7192

7293
@pytest.mark.parametrize("axis", ["index", "columns", 0, 1])
7394
def test_at_time_axis(self, axis):

pandas/tests/frame/methods/test_between_time.py

+86-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,73 @@
1-
from datetime import time
1+
from datetime import datetime, time
22

33
import numpy as np
44
import pytest
55

6-
from pandas import DataFrame, date_range
6+
from pandas._libs.tslibs import timezones
7+
import pandas.util._test_decorators as td
8+
9+
from pandas import DataFrame, Series, date_range
710
import pandas._testing as tm
811

912

1013
class TestBetweenTime:
11-
def test_between_time(self, close_open_fixture):
14+
@td.skip_if_has_locale
15+
def test_between_time_formats(self, frame_or_series):
16+
# GH#11818
1217
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
1318
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)
19+
if frame_or_series is Series:
20+
ts = ts[0]
21+
22+
strings = [
23+
("2:00", "2:30"),
24+
("0200", "0230"),
25+
("2:00am", "2:30am"),
26+
("0200am", "0230am"),
27+
("2:00:00", "2:30:00"),
28+
("020000", "023000"),
29+
("2:00:00am", "2:30:00am"),
30+
("020000am", "023000am"),
31+
]
32+
expected_length = 28
33+
34+
for time_string in strings:
35+
assert len(ts.between_time(*time_string)) == expected_length
36+
37+
@pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"])
38+
def test_localized_between_time(self, tzstr, frame_or_series):
39+
tz = timezones.maybe_get_tz(tzstr)
40+
41+
rng = date_range("4/16/2012", "5/1/2012", freq="H")
42+
ts = Series(np.random.randn(len(rng)), index=rng)
43+
if frame_or_series is DataFrame:
44+
ts = ts.to_frame()
45+
46+
ts_local = ts.tz_localize(tzstr)
47+
48+
t1, t2 = time(10, 0), time(11, 0)
49+
result = ts_local.between_time(t1, t2)
50+
expected = ts.between_time(t1, t2).tz_localize(tzstr)
51+
tm.assert_equal(result, expected)
52+
assert timezones.tz_compare(result.index.tz, tz)
53+
54+
def test_between_time_types(self, frame_or_series):
55+
# GH11818
56+
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
57+
obj = DataFrame({"A": 0}, index=rng)
58+
if frame_or_series is Series:
59+
obj = obj["A"]
60+
61+
msg = r"Cannot convert arg \[datetime\.datetime\(2010, 1, 2, 1, 0\)\] to a time"
62+
with pytest.raises(ValueError, match=msg):
63+
obj.between_time(datetime(2010, 1, 2, 1), datetime(2010, 1, 2, 5))
64+
65+
def test_between_time(self, close_open_fixture, frame_or_series):
66+
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
67+
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)
68+
if frame_or_series is not DataFrame:
69+
ts = ts[0]
70+
1471
stime = time(0, 0)
1572
etime = time(1, 0)
1673
inc_start, inc_end = close_open_fixture
@@ -37,11 +94,13 @@ def test_between_time(self, close_open_fixture):
3794

3895
result = ts.between_time("00:00", "01:00")
3996
expected = ts.between_time(stime, etime)
40-
tm.assert_frame_equal(result, expected)
97+
tm.assert_equal(result, expected)
4198

4299
# across midnight
43100
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
44101
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)
102+
if frame_or_series is not DataFrame:
103+
ts = ts[0]
45104
stime = time(22, 0)
46105
etime = time(9, 0)
47106

@@ -65,14 +124,33 @@ def test_between_time(self, close_open_fixture):
65124
else:
66125
assert (t < etime) or (t >= stime)
67126

68-
def test_between_time_raises(self):
127+
def test_between_time_raises(self, frame_or_series):
69128
# GH#20725
70-
df = DataFrame([[1, 2, 3], [4, 5, 6]])
129+
obj = DataFrame([[1, 2, 3], [4, 5, 6]])
130+
if frame_or_series is not DataFrame:
131+
obj = obj[0]
132+
71133
msg = "Index must be DatetimeIndex"
72134
with pytest.raises(TypeError, match=msg): # index is not a DatetimeIndex
73-
df.between_time(start_time="00:00", end_time="12:00")
135+
obj.between_time(start_time="00:00", end_time="12:00")
136+
137+
def test_between_time_axis(self, frame_or_series):
138+
# GH#8839
139+
rng = date_range("1/1/2000", periods=100, freq="10min")
140+
ts = Series(np.random.randn(len(rng)), index=rng)
141+
if frame_or_series is DataFrame:
142+
ts = ts.to_frame()
143+
144+
stime, etime = ("08:00:00", "09:00:00")
145+
expected_length = 7
146+
147+
assert len(ts.between_time(stime, etime)) == expected_length
148+
assert len(ts.between_time(stime, etime, axis=0)) == expected_length
149+
msg = f"No axis named {ts.ndim} for object type {type(ts).__name__}"
150+
with pytest.raises(ValueError, match=msg):
151+
ts.between_time(stime, etime, axis=ts.ndim)
74152

75-
def test_between_time_axis(self, axis):
153+
def test_between_time_axis_aliases(self, axis):
76154
# GH#8839
77155
rng = date_range("1/1/2000", periods=100, freq="10min")
78156
ts = DataFrame(np.random.randn(len(rng), len(rng)))
+64-13
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,87 @@
11
import numpy as np
22
import pytest
33

4-
from pandas import DataFrame, date_range, period_range
4+
from pandas import (
5+
DataFrame,
6+
DatetimeIndex,
7+
PeriodIndex,
8+
Series,
9+
date_range,
10+
period_range,
11+
)
512
import pandas._testing as tm
613

714

815
class TestToPeriod:
9-
def test_frame_to_period(self):
16+
def test_to_period(self, frame_or_series):
1017
K = 5
1118

12-
dr = date_range("1/1/2000", "1/1/2001")
13-
pr = period_range("1/1/2000", "1/1/2001")
14-
df = DataFrame(np.random.randn(len(dr), K), index=dr)
15-
df["mix"] = "a"
19+
dr = date_range("1/1/2000", "1/1/2001", freq="D")
20+
obj = DataFrame(
21+
np.random.randn(len(dr), K), index=dr, columns=["A", "B", "C", "D", "E"]
22+
)
23+
obj["mix"] = "a"
24+
if frame_or_series is Series:
25+
obj = obj["A"]
1626

17-
pts = df.to_period()
18-
exp = df.copy()
19-
exp.index = pr
20-
tm.assert_frame_equal(pts, exp)
27+
pts = obj.to_period()
28+
exp = obj.copy()
29+
exp.index = period_range("1/1/2000", "1/1/2001")
30+
tm.assert_equal(pts, exp)
2131

22-
pts = df.to_period("M")
23-
tm.assert_index_equal(pts.index, exp.index.asfreq("M"))
32+
pts = obj.to_period("M")
33+
exp.index = exp.index.asfreq("M")
34+
tm.assert_equal(pts, exp)
35+
36+
def test_to_period_without_freq(self, frame_or_series):
37+
# GH#7606 without freq
38+
idx = DatetimeIndex(["2011-01-01", "2011-01-02", "2011-01-03", "2011-01-04"])
39+
exp_idx = PeriodIndex(
40+
["2011-01-01", "2011-01-02", "2011-01-03", "2011-01-04"], freq="D"
41+
)
42+
43+
obj = DataFrame(np.random.randn(4, 4), index=idx, columns=idx)
44+
if frame_or_series is Series:
45+
obj = obj[idx[0]]
46+
expected = obj.copy()
47+
expected.index = exp_idx
48+
tm.assert_equal(obj.to_period(), expected)
49+
50+
if frame_or_series is DataFrame:
51+
expected = obj.copy()
52+
expected.columns = exp_idx
53+
tm.assert_frame_equal(obj.to_period(axis=1), expected)
54+
55+
def test_to_period_columns(self):
56+
dr = date_range("1/1/2000", "1/1/2001")
57+
df = DataFrame(np.random.randn(len(dr), 5), index=dr)
58+
df["mix"] = "a"
2459

2560
df = df.T
2661
pts = df.to_period(axis=1)
2762
exp = df.copy()
28-
exp.columns = pr
63+
exp.columns = period_range("1/1/2000", "1/1/2001")
2964
tm.assert_frame_equal(pts, exp)
3065

3166
pts = df.to_period("M", axis=1)
3267
tm.assert_index_equal(pts.columns, exp.columns.asfreq("M"))
3368

69+
def test_to_period_invalid_axis(self):
70+
dr = date_range("1/1/2000", "1/1/2001")
71+
df = DataFrame(np.random.randn(len(dr), 5), index=dr)
72+
df["mix"] = "a"
73+
3474
msg = "No axis named 2 for object type DataFrame"
3575
with pytest.raises(ValueError, match=msg):
3676
df.to_period(axis=2)
77+
78+
def test_to_period_raises(self, index, frame_or_series):
79+
# https://github.com/pandas-dev/pandas/issues/33327
80+
obj = Series(index=index, dtype=object)
81+
if frame_or_series is DataFrame:
82+
obj = obj.to_frame()
83+
84+
if not isinstance(index, DatetimeIndex):
85+
msg = f"unsupported Type {type(index).__name__}"
86+
with pytest.raises(TypeError, match=msg):
87+
obj.to_period()

0 commit comments

Comments
 (0)