Skip to content

Commit a44ae16

Browse files
committed
Merge remote-tracking branch 'upstream/master' into nullable-int-sum
2 parents 85d66ab + 858dec6 commit a44ae16

File tree

10 files changed

+52
-95
lines changed

10 files changed

+52
-95
lines changed

doc/source/user_guide/timeseries.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,6 @@ There are several time/date properties that one can access from ``Timestamp`` or
772772
week,"The week ordinal of the year"
773773
dayofweek,"The number of the day of the week with Monday=0, Sunday=6"
774774
weekday,"The number of the day of the week with Monday=0, Sunday=6"
775-
isocalendar,"The ISO 8601 year, week and day of the date"
776775
quarter,"Quarter of the date: Jan-Mar = 1, Apr-Jun = 2, etc."
777776
days_in_month,"The number of days in the month of the datetime"
778777
is_month_start,"Logical indicating if first day of month (defined by frequency)"
@@ -794,7 +793,7 @@ You may obtain the year, week and day components of the ISO year from the ISO 86
794793
.. ipython:: python
795794
796795
idx = pd.date_range(start='2019-12-29', freq='D', periods=4)
797-
idx.to_series().dt.isocalendar
796+
idx.to_series().dt.isocalendar()
798797
799798
.. _timeseries.offsets:
800799

doc/source/whatsnew/v1.1.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Other enhancements
8888
- :class:`Series.str` now has a `fullmatch` method that matches a regular expression against the entire string in each row of the series, similar to `re.fullmatch` (:issue:`32806`).
8989
- :meth:`DataFrame.sample` will now also allow array-like and BitGenerator objects to be passed to ``random_state`` as seeds (:issue:`32503`)
9090
- :meth:`MultiIndex.union` will now raise `RuntimeWarning` if the object inside are unsortable, pass `sort=False` to suppress this warning (:issue:`33015`)
91-
- :class:`Series.dt` and :class:`DatatimeIndex` now have an `isocalendar` accessor that returns a :class:`DataFrame` with year, week, and day calculated according to the ISO 8601 calendar (:issue:`33206`).
91+
- :class:`Series.dt` and :class:`DatatimeIndex` now have an `isocalendar` method that returns a :class:`DataFrame` with year, week, and day calculated according to the ISO 8601 calendar (:issue:`33206`).
9292
- The :meth:`DataFrame.to_feather` method now supports additional keyword
9393
arguments (e.g. to set the compression) that are added in pyarrow 0.17
9494
(:issue:`33422`).

pandas/core/arrays/datetimes.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ class DatetimeArray(dtl.DatetimeLikeArrayMixin, dtl.TimelikeOps, dtl.DatelikeOps
183183
"microsecond",
184184
"nanosecond",
185185
]
186-
_other_ops = ["date", "time", "timetz", "isocalendar"]
186+
_other_ops = ["date", "time", "timetz"]
187187
_datetimelike_ops = _field_ops + _object_ops + _bool_ops + _other_ops
188188
_datetimelike_methods = [
189189
"to_period",
@@ -1242,7 +1242,6 @@ def date(self):
12421242

12431243
return tslib.ints_to_pydatetime(timestamps, box="date")
12441244

1245-
@property
12461245
def isocalendar(self):
12471246
"""
12481247
Returns a DataFrame with the year, week, and day calculated according to
@@ -1263,13 +1262,13 @@ def isocalendar(self):
12631262
Examples
12641263
--------
12651264
>>> idx = pd.date_range(start='2019-12-29', freq='D', periods=4)
1266-
>>> idx.isocalendar
1265+
>>> idx.isocalendar()
12671266
year week day
12681267
0 2019 52 7
12691268
1 2020 1 1
12701269
2 2020 1 2
12711270
3 2020 1 3
1272-
>>> idx.isocalendar.week
1271+
>>> idx.isocalendar().week
12731272
0 52
12741273
1 1
12751274
2 1

pandas/core/indexes/accessors.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ def to_pydatetime(self) -> np.ndarray:
219219
def freq(self):
220220
return self._get_values().inferred_freq
221221

222-
@property
223222
def isocalendar(self):
224223
"""
225224
Returns a DataFrame with the year, week, and day calculated according to
@@ -240,16 +239,16 @@ def isocalendar(self):
240239
Examples
241240
--------
242241
>>> ser = pd.to_datetime(pd.Series(["2010-01-01", pd.NaT]))
243-
>>> ser.dt.isocalendar
242+
>>> ser.dt.isocalendar()
244243
year week day
245244
0 2009 53 5
246245
1 <NA> <NA> <NA>
247-
>>> ser.dt.isocalendar.week
246+
>>> ser.dt.isocalendar().week
248247
0 53
249248
1 <NA>
250249
Name: week, dtype: UInt32
251250
"""
252-
return self._get_values().isocalendar.set_index(self._parent.index)
251+
return self._get_values().isocalendar().set_index(self._parent.index)
253252

254253

255254
@delegate_names(

pandas/core/nanops.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,11 +300,8 @@ def _get_values(
300300
dtype, fill_value=fill_value, fill_value_typ=fill_value_typ
301301
)
302302

303-
copy = (mask is not None) and (fill_value is not None)
304-
305-
if skipna and copy:
303+
if skipna and (mask is not None) and (fill_value is not None):
306304
values = values.copy()
307-
assert mask is not None # for mypy
308305
if dtype_ok and mask.any():
309306
np.putmask(values, mask, fill_value)
310307

pandas/tests/arrays/categorical/test_analytics.py

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -53,40 +53,28 @@ def test_min_max_ordered(self):
5353
@pytest.mark.parametrize("aggregation", ["min", "max"])
5454
def test_min_max_ordered_empty(self, categories, expected, aggregation):
5555
# GH 30227
56-
cat = Categorical([], categories=list("ABC"), ordered=True)
56+
cat = Categorical([], categories=categories, ordered=True)
5757

5858
agg_func = getattr(cat, aggregation)
5959
result = agg_func()
6060
assert result is expected
6161

62+
@pytest.mark.parametrize(
63+
"values, categories",
64+
[(["a", "b", "c", np.nan], list("cba")), ([1, 2, 3, np.nan], [3, 2, 1])],
65+
)
6266
@pytest.mark.parametrize("skipna", [True, False])
63-
def test_min_max_with_nan(self, skipna):
67+
@pytest.mark.parametrize("function", ["min", "max"])
68+
def test_min_max_with_nan(self, values, categories, function, skipna):
6469
# GH 25303
65-
cat = Categorical(
66-
[np.nan, "b", "c", np.nan], categories=["d", "c", "b", "a"], ordered=True
67-
)
68-
_min = cat.min(skipna=skipna)
69-
_max = cat.max(skipna=skipna)
70-
71-
if skipna is False:
72-
assert np.isnan(_min)
73-
assert np.isnan(_max)
74-
else:
75-
assert _min == "c"
76-
assert _max == "b"
77-
78-
cat = Categorical(
79-
[np.nan, 1, 2, np.nan], categories=[5, 4, 3, 2, 1], ordered=True
80-
)
81-
_min = cat.min(skipna=skipna)
82-
_max = cat.max(skipna=skipna)
70+
cat = Categorical(values, categories=categories, ordered=True)
71+
result = getattr(cat, function)(skipna=skipna)
8372

8473
if skipna is False:
85-
assert np.isnan(_min)
86-
assert np.isnan(_max)
74+
assert result is np.nan
8775
else:
88-
assert _min == 2
89-
assert _max == 1
76+
expected = categories[0] if function == "min" else categories[2]
77+
assert result == expected
9078

9179
@pytest.mark.parametrize("function", ["min", "max"])
9280
@pytest.mark.parametrize("skipna", [True, False])

pandas/tests/dtypes/test_missing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ def test_checknull(self):
564564
for value in never_na_vals:
565565
assert not libmissing.checknull(value)
566566

567-
def checknull_old(self):
567+
def test_checknull_old(self):
568568
for value in na_vals:
569569
assert libmissing.checknull_old(value)
570570

pandas/tests/indexes/multi/test_indexing.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,10 +605,6 @@ def test_get_loc_nan(self, level, nulls_fixture):
605605
key = ["b", "d"]
606606
levels[level] = np.array([0, nulls_fixture], dtype=type(nulls_fixture))
607607
key[level] = nulls_fixture
608-
609-
if nulls_fixture is pd.NA:
610-
pytest.xfail("MultiIndex from pd.NA in np.array broken; see GH 31883")
611-
612608
idx = MultiIndex.from_product(levels)
613609
assert idx.get_loc(tuple(key)) == 3
614610

pandas/tests/reductions/test_reductions.py

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,67 +1072,45 @@ class TestCategoricalSeriesReductions:
10721072
# were moved from a series-specific test file, _not_ that these tests are
10731073
# intended long-term to be series-specific
10741074

1075-
def test_min_max(self):
1075+
@pytest.mark.parametrize("function", ["min", "max"])
1076+
def test_min_max_unordered_raises(self, function):
10761077
# unordered cats have no min/max
10771078
cat = Series(Categorical(["a", "b", "c", "d"], ordered=False))
1078-
with pytest.raises(TypeError):
1079-
cat.min()
1080-
with pytest.raises(TypeError):
1081-
cat.max()
1082-
1083-
cat = Series(Categorical(["a", "b", "c", "d"], ordered=True))
1084-
_min = cat.min()
1085-
_max = cat.max()
1086-
assert _min == "a"
1087-
assert _max == "d"
1088-
1089-
cat = Series(
1090-
Categorical(
1091-
["a", "b", "c", "d"], categories=["d", "c", "b", "a"], ordered=True
1092-
)
1093-
)
1094-
_min = cat.min()
1095-
_max = cat.max()
1096-
assert _min == "d"
1097-
assert _max == "a"
1098-
1099-
cat = Series(
1100-
Categorical(
1101-
[np.nan, "b", "c", np.nan],
1102-
categories=["d", "c", "b", "a"],
1103-
ordered=True,
1104-
)
1105-
)
1106-
_min = cat.min()
1107-
_max = cat.max()
1108-
assert _min == "c"
1109-
assert _max == "b"
1079+
msg = f"Categorical is not ordered for operation {function}"
1080+
with pytest.raises(TypeError, match=msg):
1081+
getattr(cat, function)()
11101082

1111-
cat = Series(
1112-
Categorical(
1113-
[np.nan, 1, 2, np.nan], categories=[5, 4, 3, 2, 1], ordered=True
1114-
)
1115-
)
1116-
_min = cat.min()
1117-
_max = cat.max()
1118-
assert _min == 2
1119-
assert _max == 1
1083+
@pytest.mark.parametrize(
1084+
"values, categories",
1085+
[
1086+
(list("abc"), list("abc")),
1087+
(list("abc"), list("cba")),
1088+
(list("abc") + [np.nan], list("cba")),
1089+
([1, 2, 3], [3, 2, 1]),
1090+
([1, 2, 3, np.nan], [3, 2, 1]),
1091+
],
1092+
)
1093+
@pytest.mark.parametrize("function", ["min", "max"])
1094+
def test_min_max_ordered(self, values, categories, function):
1095+
# GH 25303
1096+
cat = Series(Categorical(values, categories=categories, ordered=True))
1097+
result = getattr(cat, function)(skipna=True)
1098+
expected = categories[0] if function == "min" else categories[2]
1099+
assert result == expected
11201100

1101+
@pytest.mark.parametrize("function", ["min", "max"])
11211102
@pytest.mark.parametrize("skipna", [True, False])
1122-
def test_min_max_skipna(self, skipna):
1123-
# GH 25303
1103+
def test_min_max_skipna(self, function, skipna):
11241104
cat = Series(
11251105
Categorical(["a", "b", np.nan, "a"], categories=["b", "a"], ordered=True)
11261106
)
1127-
_min = cat.min(skipna=skipna)
1128-
_max = cat.max(skipna=skipna)
1107+
result = getattr(cat, function)(skipna=skipna)
11291108

11301109
if skipna is True:
1131-
assert _min == "b"
1132-
assert _max == "a"
1110+
expected = "b" if function == "min" else "a"
1111+
assert result == expected
11331112
else:
1134-
assert np.isnan(_min)
1135-
assert np.isnan(_max)
1113+
assert result is np.nan
11361114

11371115

11381116
class TestSeriesMode:

pandas/tests/series/test_datetime_values.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def test_dt_namespace_accessor(self):
4949
"ceil",
5050
"day_name",
5151
"month_name",
52+
"isocalendar",
5253
]
5354
ok_for_td = TimedeltaIndex._datetimelike_ops
5455
ok_for_td_methods = [
@@ -678,7 +679,7 @@ def test_setitem_with_different_tz(self):
678679
],
679680
)
680681
def test_isocalendar(self, input_series, expected_output):
681-
result = pd.to_datetime(pd.Series(input_series)).dt.isocalendar
682+
result = pd.to_datetime(pd.Series(input_series)).dt.isocalendar()
682683
expected_frame = pd.DataFrame(
683684
expected_output, columns=["year", "week", "day"], dtype="UInt32"
684685
)

0 commit comments

Comments
 (0)