Skip to content

Commit b55db71

Browse files
committed
Merge remote-tracking branch 'upstream/master' into styler_to_html
2 parents dda33de + 0158382 commit b55db71

31 files changed

+679
-449
lines changed

ci/code_checks.sh

Lines changed: 28 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -106,84 +106,34 @@ fi
106106
### DOCTESTS ###
107107
if [[ -z "$CHECK" || "$CHECK" == "doctests" ]]; then
108108

109-
# Individual files
110-
111-
MSG='Doctests accessor.py' ; echo $MSG
112-
pytest -q --doctest-modules pandas/core/accessor.py
113-
RET=$(($RET + $?)) ; echo $MSG "DONE"
114-
115-
MSG='Doctests aggregation.py' ; echo $MSG
116-
pytest -q --doctest-modules pandas/core/aggregation.py
117-
RET=$(($RET + $?)) ; echo $MSG "DONE"
118-
119-
MSG='Doctests base.py' ; echo $MSG
120-
pytest -q --doctest-modules pandas/core/base.py
121-
RET=$(($RET + $?)) ; echo $MSG "DONE"
122-
123-
MSG='Doctests construction.py' ; echo $MSG
124-
pytest -q --doctest-modules pandas/core/construction.py
125-
RET=$(($RET + $?)) ; echo $MSG "DONE"
126-
127-
MSG='Doctests frame.py' ; echo $MSG
128-
pytest -q --doctest-modules pandas/core/frame.py
129-
RET=$(($RET + $?)) ; echo $MSG "DONE"
130-
131-
MSG='Doctests generic.py' ; echo $MSG
132-
pytest -q --doctest-modules pandas/core/generic.py
133-
RET=$(($RET + $?)) ; echo $MSG "DONE"
134-
135-
MSG='Doctests series.py' ; echo $MSG
136-
pytest -q --doctest-modules pandas/core/series.py
137-
RET=$(($RET + $?)) ; echo $MSG "DONE"
138-
139-
MSG='Doctests strings.py' ; echo $MSG
140-
pytest -q --doctest-modules pandas/core/strings/
141-
RET=$(($RET + $?)) ; echo $MSG "DONE"
142-
143-
MSG='Doctests sql.py' ; echo $MSG
144-
pytest -q --doctest-modules pandas/io/sql.py
145-
RET=$(($RET + $?)) ; echo $MSG "DONE"
146-
147-
# Directories
148-
149-
MSG='Doctests arrays'; echo $MSG
150-
pytest -q --doctest-modules pandas/core/arrays/
151-
RET=$(($RET + $?)) ; echo $MSG "DONE"
152-
153-
MSG='Doctests computation' ; echo $MSG
154-
pytest -q --doctest-modules pandas/core/computation/
155-
RET=$(($RET + $?)) ; echo $MSG "DONE"
156-
157-
MSG='Doctests dtypes'; echo $MSG
158-
pytest -q --doctest-modules pandas/core/dtypes/
159-
RET=$(($RET + $?)) ; echo $MSG "DONE"
160-
161-
MSG='Doctests groupby' ; echo $MSG
162-
pytest -q --doctest-modules pandas/core/groupby/
163-
RET=$(($RET + $?)) ; echo $MSG "DONE"
164-
165-
MSG='Doctests indexes' ; echo $MSG
166-
pytest -q --doctest-modules pandas/core/indexes/
167-
RET=$(($RET + $?)) ; echo $MSG "DONE"
168-
169-
MSG='Doctests ops' ; echo $MSG
170-
pytest -q --doctest-modules pandas/core/ops/
171-
RET=$(($RET + $?)) ; echo $MSG "DONE"
172-
173-
MSG='Doctests reshape' ; echo $MSG
174-
pytest -q --doctest-modules pandas/core/reshape/
175-
RET=$(($RET + $?)) ; echo $MSG "DONE"
176-
177-
MSG='Doctests tools' ; echo $MSG
178-
pytest -q --doctest-modules pandas/core/tools/
179-
RET=$(($RET + $?)) ; echo $MSG "DONE"
180-
181-
MSG='Doctests window' ; echo $MSG
182-
pytest -q --doctest-modules pandas/core/window/
183-
RET=$(($RET + $?)) ; echo $MSG "DONE"
184-
185-
MSG='Doctests tseries' ; echo $MSG
186-
pytest -q --doctest-modules pandas/tseries/
109+
MSG='Doctests for individual files' ; echo $MSG
110+
pytest -q --doctest-modules \
111+
pandas/core/accessor.py \
112+
pandas/core/aggregation.py \
113+
pandas/core/algorithms.py \
114+
pandas/core/base.py \
115+
pandas/core/construction.py \
116+
pandas/core/frame.py \
117+
pandas/core/generic.py \
118+
pandas/core/indexers.py \
119+
pandas/core/nanops.py \
120+
pandas/core/series.py \
121+
pandas/io/sql.py
122+
RET=$(($RET + $?)) ; echo $MSG "DONE"
123+
124+
MSG='Doctests for directories' ; echo $MSG
125+
pytest -q --doctest-modules \
126+
pandas/core/arrays/ \
127+
pandas/core/computation/ \
128+
pandas/core/dtypes/ \
129+
pandas/core/groupby/ \
130+
pandas/core/indexes/ \
131+
pandas/core/ops/ \
132+
pandas/core/reshape/ \
133+
pandas/core/strings/ \
134+
pandas/core/tools/ \
135+
pandas/core/window/ \
136+
pandas/tseries/
187137
RET=$(($RET + $?)) ; echo $MSG "DONE"
188138

189139
fi

doc/source/whatsnew/v1.3.0.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ Deprecations
609609
- Deprecated using :func:`merge` or :func:`join` on a different number of levels (:issue:`34862`)
610610
- Deprecated the use of ``**kwargs`` in :class:`.ExcelWriter`; use the keyword argument ``engine_kwargs`` instead (:issue:`40430`)
611611
- Deprecated the ``level`` keyword for :class:`DataFrame` and :class:`Series` aggregations; use groupby instead (:issue:`39983`)
612-
- The ``inplace`` parameter of :meth:`Categorical.remove_categories`, :meth:`Categorical.add_categories` is deprecated and will be removed in a future version (:issue:`37643`)
612+
- The ``inplace`` parameter of :meth:`Categorical.remove_categories`, :meth:`Categorical.add_categories`, :meth:`Categorical.reorder_categories` is deprecated and will be removed in a future version (:issue:`37643`)
613613
- Deprecated :func:`merge` producing duplicated columns through the ``suffixes`` keyword and already existing columns (:issue:`22818`)
614614

615615
.. ---------------------------------------------------------------------------
@@ -848,6 +848,8 @@ Groupby/resample/rolling
848848
- Bug in :meth:`GroupBy.cummin` and :meth:`GroupBy.cummax` incorrectly rounding integer values near the ``int64`` implementations bounds (:issue:`40767`)
849849
- Bug in :meth:`.GroupBy.rank` with nullable dtypes incorrectly raising ``TypeError`` (:issue:`41010`)
850850
- Bug in :meth:`.GroupBy.cummin` and :meth:`.GroupBy.cummax` computing wrong result with nullable data types too large to roundtrip when casting to float (:issue:`37493`)
851+
- Bug in :meth:`DataFrame.rolling` returning mean zero for all ``NaN`` window with ``min_periods=0`` if calculation is not numerical stable (:issue:`41053`)
852+
- Bug in :meth:`DataFrame.rolling` returning sum not zero for all ``NaN`` window with ``min_periods=0`` if calculation is not numerical stable (:issue:`41053`)
851853

852854
Reshaping
853855
^^^^^^^^^

pandas/_libs/window/aggregations.pyx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ cdef inline float64_t calc_sum(int64_t minp, int64_t nobs, float64_t sum_x) nogi
7373
cdef:
7474
float64_t result
7575

76-
if nobs >= minp:
76+
if nobs == 0 == minp:
77+
result = 0
78+
elif nobs >= minp:
7779
result = sum_x
7880
else:
7981
result = NaN
@@ -170,7 +172,7 @@ cdef inline float64_t calc_mean(int64_t minp, Py_ssize_t nobs,
170172
cdef:
171173
float64_t result
172174

173-
if nobs >= minp:
175+
if nobs >= minp and nobs > 0:
174176
result = sum_x / <float64_t>nobs
175177
if neg_ct == 0 and result < 0:
176178
# all positive

pandas/core/algorithms.py

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -375,46 +375,60 @@ def unique(values):
375375
>>> pd.unique(pd.Series([2] + [1] * 5))
376376
array([2, 1])
377377
378-
>>> pd.unique(pd.Series([pd.Timestamp('20160101'),
379-
... pd.Timestamp('20160101')]))
378+
>>> pd.unique(pd.Series([pd.Timestamp("20160101"), pd.Timestamp("20160101")]))
380379
array(['2016-01-01T00:00:00.000000000'], dtype='datetime64[ns]')
381380
382-
>>> pd.unique(pd.Series([pd.Timestamp('20160101', tz='US/Eastern'),
383-
... pd.Timestamp('20160101', tz='US/Eastern')]))
384-
array([Timestamp('2016-01-01 00:00:00-0500', tz='US/Eastern')],
385-
dtype=object)
386-
387-
>>> pd.unique(pd.Index([pd.Timestamp('20160101', tz='US/Eastern'),
388-
... pd.Timestamp('20160101', tz='US/Eastern')]))
381+
>>> pd.unique(
382+
... pd.Series(
383+
... [
384+
... pd.Timestamp("20160101", tz="US/Eastern"),
385+
... pd.Timestamp("20160101", tz="US/Eastern"),
386+
... ]
387+
... )
388+
... )
389+
<DatetimeArray>
390+
['2016-01-01 00:00:00-05:00']
391+
Length: 1, dtype: datetime64[ns, US/Eastern]
392+
393+
>>> pd.unique(
394+
... pd.Index(
395+
... [
396+
... pd.Timestamp("20160101", tz="US/Eastern"),
397+
... pd.Timestamp("20160101", tz="US/Eastern"),
398+
... ]
399+
... )
400+
... )
389401
DatetimeIndex(['2016-01-01 00:00:00-05:00'],
390-
... dtype='datetime64[ns, US/Eastern]', freq=None)
402+
dtype='datetime64[ns, US/Eastern]',
403+
freq=None)
391404
392-
>>> pd.unique(list('baabc'))
405+
>>> pd.unique(list("baabc"))
393406
array(['b', 'a', 'c'], dtype=object)
394407
395408
An unordered Categorical will return categories in the
396409
order of appearance.
397410
398-
>>> pd.unique(pd.Series(pd.Categorical(list('baabc'))))
399-
[b, a, c]
400-
Categories (3, object): [b, a, c]
411+
>>> pd.unique(pd.Series(pd.Categorical(list("baabc"))))
412+
['b', 'a', 'c']
413+
Categories (3, object): ['a', 'b', 'c']
401414
402-
>>> pd.unique(pd.Series(pd.Categorical(list('baabc'),
403-
... categories=list('abc'))))
404-
[b, a, c]
405-
Categories (3, object): [b, a, c]
415+
>>> pd.unique(pd.Series(pd.Categorical(list("baabc"), categories=list("abc"))))
416+
['b', 'a', 'c']
417+
Categories (3, object): ['a', 'b', 'c']
406418
407419
An ordered Categorical preserves the category ordering.
408420
409-
>>> pd.unique(pd.Series(pd.Categorical(list('baabc'),
410-
... categories=list('abc'),
411-
... ordered=True)))
412-
[b, a, c]
413-
Categories (3, object): [a < b < c]
421+
>>> pd.unique(
422+
... pd.Series(
423+
... pd.Categorical(list("baabc"), categories=list("abc"), ordered=True)
424+
... )
425+
... )
426+
['b', 'a', 'c']
427+
Categories (3, object): ['a' < 'b' < 'c']
414428
415429
An array of tuples
416430
417-
>>> pd.unique([('a', 'b'), ('b', 'a'), ('a', 'c'), ('b', 'a')])
431+
>>> pd.unique([("a", "b"), ("b", "a"), ("a", "c"), ("b", "a")])
418432
array([('a', 'b'), ('b', 'a'), ('a', 'c')], dtype=object)
419433
"""
420434
values = _ensure_arraylike(values)

pandas/core/arrays/categorical.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ def rename_categories(self, new_categories, inplace=False):
10311031
if not inplace:
10321032
return cat
10331033

1034-
def reorder_categories(self, new_categories, ordered=None, inplace=False):
1034+
def reorder_categories(self, new_categories, ordered=None, inplace=no_default):
10351035
"""
10361036
Reorder categories as specified in new_categories.
10371037
@@ -1049,6 +1049,8 @@ def reorder_categories(self, new_categories, ordered=None, inplace=False):
10491049
Whether or not to reorder the categories inplace or return a copy of
10501050
this categorical with reordered categories.
10511051
1052+
.. deprecated:: 1.3.0
1053+
10521054
Returns
10531055
-------
10541056
cat : Categorical or None
@@ -1068,6 +1070,18 @@ def reorder_categories(self, new_categories, ordered=None, inplace=False):
10681070
remove_unused_categories : Remove categories which are not used.
10691071
set_categories : Set the categories to the specified ones.
10701072
"""
1073+
if inplace is not no_default:
1074+
warn(
1075+
"The `inplace` parameter in pandas.Categorical."
1076+
"reorder_categories is deprecated and will be removed in "
1077+
"a future version. Removing unused categories will always "
1078+
"return a new Categorical object.",
1079+
FutureWarning,
1080+
stacklevel=2,
1081+
)
1082+
else:
1083+
inplace = False
1084+
10711085
inplace = validate_bool_kwarg(inplace, "inplace")
10721086
if set(self.dtype.categories) != set(new_categories):
10731087
raise ValueError(

pandas/core/generic.py

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6474,13 +6474,53 @@ def fillna(
64746474
else:
64756475
return result.__finalize__(self, method="fillna")
64766476

6477+
@overload
6478+
def ffill(
6479+
self: FrameOrSeries,
6480+
axis: None | Axis = ...,
6481+
inplace: Literal[False] = ...,
6482+
limit: None | int = ...,
6483+
downcast=...,
6484+
) -> FrameOrSeries:
6485+
...
6486+
6487+
@overload
6488+
def ffill(
6489+
self: FrameOrSeries,
6490+
axis: None | Axis,
6491+
inplace: Literal[True],
6492+
limit: None | int = ...,
6493+
downcast=...,
6494+
) -> None:
6495+
...
6496+
6497+
@overload
6498+
def ffill(
6499+
self: FrameOrSeries,
6500+
*,
6501+
inplace: Literal[True],
6502+
limit: None | int = ...,
6503+
downcast=...,
6504+
) -> None:
6505+
...
6506+
6507+
@overload
6508+
def ffill(
6509+
self: FrameOrSeries,
6510+
axis: None | Axis = ...,
6511+
inplace: bool_t = ...,
6512+
limit: None | int = ...,
6513+
downcast=...,
6514+
) -> FrameOrSeries | None:
6515+
...
6516+
64776517
@final
64786518
@doc(klass=_shared_doc_kwargs["klass"])
64796519
def ffill(
64806520
self: FrameOrSeries,
6481-
axis=None,
6521+
axis: None | Axis = None,
64826522
inplace: bool_t = False,
6483-
limit=None,
6523+
limit: None | int = None,
64846524
downcast=None,
64856525
) -> FrameOrSeries | None:
64866526
"""
@@ -6497,13 +6537,53 @@ def ffill(
64976537

64986538
pad = ffill
64996539

6540+
@overload
6541+
def bfill(
6542+
self: FrameOrSeries,
6543+
axis: None | Axis = ...,
6544+
inplace: Literal[False] = ...,
6545+
limit: None | int = ...,
6546+
downcast=...,
6547+
) -> FrameOrSeries:
6548+
...
6549+
6550+
@overload
6551+
def bfill(
6552+
self: FrameOrSeries,
6553+
axis: None | Axis,
6554+
inplace: Literal[True],
6555+
limit: None | int = ...,
6556+
downcast=...,
6557+
) -> None:
6558+
...
6559+
6560+
@overload
6561+
def bfill(
6562+
self: FrameOrSeries,
6563+
*,
6564+
inplace: Literal[True],
6565+
limit: None | int = ...,
6566+
downcast=...,
6567+
) -> None:
6568+
...
6569+
6570+
@overload
6571+
def bfill(
6572+
self: FrameOrSeries,
6573+
axis: None | Axis = ...,
6574+
inplace: bool_t = ...,
6575+
limit: None | int = ...,
6576+
downcast=...,
6577+
) -> FrameOrSeries | None:
6578+
...
6579+
65006580
@final
65016581
@doc(klass=_shared_doc_kwargs["klass"])
65026582
def bfill(
65036583
self: FrameOrSeries,
6504-
axis=None,
6584+
axis: None | Axis = None,
65056585
inplace: bool_t = False,
6506-
limit=None,
6586+
limit: None | int = None,
65076587
downcast=None,
65086588
) -> FrameOrSeries | None:
65096589
"""

0 commit comments

Comments
 (0)