Skip to content

Commit 37e8a82

Browse files
committed
Merge remote-tracking branch 'upstream/master' into move-metadata-to-cfg
2 parents 94c8eff + eb17d3d commit 37e8a82

File tree

22 files changed

+137
-94
lines changed

22 files changed

+137
-94
lines changed

doc/source/_static/css/pandas.css

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/* Override some aspects of the pydata-sphinx-theme */
2+
3+
:root {
4+
/* Use softer blue from bootstrap's default info color */
5+
--color-info: 23, 162, 184;
6+
}
7+
18
/* Getting started index page */
29

310
.intro-card {

doc/source/whatsnew/v1.2.1.rst

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ including other versions of pandas.
1515
Fixed regressions
1616
~~~~~~~~~~~~~~~~~
1717
- Fixed regression in :meth:`~DataFrame.to_csv` that created corrupted zip files when there were more rows than ``chunksize`` (:issue:`38714`)
18+
- Fixed regression in :meth:`~DataFrame.to_csv` opening ``codecs.StreamReaderWriter`` in binary mode instead of in text mode (:issue:`39247`)
1819
- Fixed regression in :meth:`read_csv` and other read functions were the encoding error policy (``errors``) did not default to ``"replace"`` when no encoding was specified (:issue:`38989`)
1920
- Fixed regression in :func:`read_excel` with non-rawbyte file handles (:issue:`38788`)
2021
- Fixed regression in :meth:`DataFrame.to_stata` not removing the created file when an error occured (:issue:`39202`)
@@ -31,6 +32,7 @@ Fixed regressions
3132
- Fixed regression in :meth:`DataFrame.replace` raising ``ValueError`` when :class:`DataFrame` has dtype ``bytes`` (:issue:`38900`)
3233
- Fixed regression in :meth:`Series.fillna` that raised ``RecursionError`` with ``datetime64[ns, UTC]`` dtype (:issue:`38851`)
3334
- Fixed regression in comparisons between ``NaT`` and ``datetime.date`` objects incorrectly returning ``True`` (:issue:`39151`)
35+
- Fixed regression in calling NumPy :func:`~numpy.ufunc.accumulate` ufuncs on DataFrames, e.g. ``np.maximum.accumulate(df)`` (:issue:`39259`)
3436
- Fixed regression in repr of float-like strings of an ``object`` dtype having trailing 0's truncated after the decimal (:issue:`38708`)
3537
- Fixed regression that raised ``AttributeError`` with PyArrow versions [0.16.0, 1.0.0) (:issue:`38801`)
3638
- Fixed regression in :func:`pandas.testing.assert_frame_equal` raising ``TypeError`` with ``check_like=True`` when :class:`Index` or columns have mixed dtype (:issue:`39168`)

doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ Deprecations
194194
- Deprecated comparison of :class:`Timestamp` object with ``datetime.date`` objects. Instead of e.g. ``ts <= mydate`` use ``ts <= pd.Timestamp(mydate)`` or ``ts.date() <= mydate`` (:issue:`36131`)
195195
- Deprecated :attr:`Rolling.win_type` returning ``"freq"`` (:issue:`38963`)
196196
- Deprecated :attr:`Rolling.is_datetimelike` (:issue:`38963`)
197+
- Deprecated :meth:`core.window.ewm.ExponentialMovingWindow.vol` (:issue:`39220`)
197198
-
198199

199200
.. ---------------------------------------------------------------------------

pandas/core/arraylike.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,14 @@ def reconstruct(result):
274274
result = getattr(ufunc, method)(*inputs, **kwargs)
275275
else:
276276
# ufunc(dataframe)
277-
mgr = inputs[0]._mgr
278-
result = mgr.apply(getattr(ufunc, method))
277+
if method == "__call__":
278+
# for np.<ufunc>(..) calls
279+
mgr = inputs[0]._mgr
280+
result = mgr.apply(getattr(ufunc, method))
281+
else:
282+
# otherwise specific ufunc methods (eg np.<ufunc>.accumulate(..))
283+
# Those can have an axis keyword and thus can't be called block-by-block
284+
result = getattr(ufunc, method)(np.asarray(inputs[0]), **kwargs)
279285

280286
if ufunc.nout > 1: # type: ignore[attr-defined]
281287
result = tuple(reconstruct(x) for x in result)

pandas/core/computation/expr.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -558,19 +558,19 @@ def visit_Index(self, node, **kwargs):
558558
return self.visit(node.value)
559559

560560
def visit_Subscript(self, node, **kwargs):
561-
import pandas as pd
561+
from pandas import eval as pd_eval
562562

563563
value = self.visit(node.value)
564564
slobj = self.visit(node.slice)
565-
result = pd.eval(
565+
result = pd_eval(
566566
slobj, local_dict=self.env, engine=self.engine, parser=self.parser
567567
)
568568
try:
569569
# a Term instance
570570
v = value.value[result]
571571
except AttributeError:
572572
# an Op instance
573-
lhs = pd.eval(
573+
lhs = pd_eval(
574574
value, local_dict=self.env, engine=self.engine, parser=self.parser
575575
)
576576
v = lhs[result]

pandas/core/computation/pytables.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212

1313
from pandas.core.dtypes.common import is_list_like
1414

15-
import pandas as pd
1615
import pandas.core.common as com
1716
from pandas.core.computation import expr, ops, scope as _scope
1817
from pandas.core.computation.common import ensure_decoded
1918
from pandas.core.computation.expr import BaseExprVisitor
2019
from pandas.core.computation.ops import UndefinedVariableError, is_term
2120
from pandas.core.construction import extract_array
21+
from pandas.core.indexes.base import Index
2222

2323
from pandas.io.formats.printing import pprint_thing, pprint_thing_encoded
2424

@@ -250,7 +250,7 @@ def convert_values(self):
250250

251251

252252
class FilterBinOp(BinOp):
253-
filter: Optional[Tuple[Any, Any, pd.Index]] = None
253+
filter: Optional[Tuple[Any, Any, Index]] = None
254254

255255
def __repr__(self) -> str:
256256
if self.filter is None:
@@ -285,7 +285,7 @@ def evaluate(self):
285285
if self.op in ["==", "!="] and len(values) > self._max_selectors:
286286

287287
filter_op = self.generate_filter_op()
288-
self.filter = (self.lhs, filter_op, pd.Index(values))
288+
self.filter = (self.lhs, filter_op, Index(values))
289289

290290
return self
291291
return None
@@ -294,7 +294,7 @@ def evaluate(self):
294294
if self.op in ["==", "!="]:
295295

296296
filter_op = self.generate_filter_op()
297-
self.filter = (self.lhs, filter_op, pd.Index(values))
297+
self.filter = (self.lhs, filter_op, Index(values))
298298

299299
else:
300300
raise TypeError(

pandas/core/generic.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -8935,9 +8935,7 @@ def _where(
89358935
# reconstruct the block manager
89368936

89378937
self._check_inplace_setting(other)
8938-
new_data = self._mgr.putmask(
8939-
mask=cond, new=other, align=align, axis=block_axis
8940-
)
8938+
new_data = self._mgr.putmask(mask=cond, new=other, align=align)
89418939
result = self._constructor(new_data)
89428940
return self._update_inplace(result)
89438941

pandas/core/internals/__init__.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
from pandas.core.internals.base import DataManager
33
from pandas.core.internals.blocks import ( # io.pytables, io.packers
44
Block,
5-
BoolBlock,
65
CategoricalBlock,
7-
ComplexBlock,
86
DatetimeBlock,
97
DatetimeTZBlock,
108
ExtensionBlock,
119
FloatBlock,
12-
IntBlock,
10+
NumericBlock,
1311
ObjectBlock,
1412
TimeDeltaBlock,
1513
make_block,
@@ -25,14 +23,12 @@
2523

2624
__all__ = [
2725
"Block",
28-
"BoolBlock",
2926
"CategoricalBlock",
30-
"ComplexBlock",
27+
"NumericBlock",
3128
"DatetimeBlock",
3229
"DatetimeTZBlock",
3330
"ExtensionBlock",
3431
"FloatBlock",
35-
"IntBlock",
3632
"ObjectBlock",
3733
"TimeDeltaBlock",
3834
"safe_reshape",

pandas/core/internals/array_manager.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ def where(self, other, cond, align: bool, errors: str, axis: int) -> ArrayManage
343343
# def setitem(self, indexer, value) -> ArrayManager:
344344
# return self.apply_with_block("setitem", indexer=indexer, value=value)
345345

346-
def putmask(self, mask, new, align: bool = True, axis: int = 0):
346+
def putmask(self, mask, new, align: bool = True):
347347

348348
if align:
349349
align_keys = ["new", "mask"]
@@ -356,7 +356,6 @@ def putmask(self, mask, new, align: bool = True, axis: int = 0):
356356
align_keys=align_keys,
357357
mask=mask,
358358
new=new,
359-
axis=axis,
360359
)
361360

362361
def diff(self, n: int, axis: int) -> ArrayManager:

pandas/core/internals/blocks.py

+22-40
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ class Block(PandasObject):
100100
__slots__ = ["_mgr_locs", "values", "ndim"]
101101
is_numeric = False
102102
is_float = False
103-
is_integer = False
104-
is_complex = False
105103
is_datetime = False
106104
is_datetimetz = False
107105
is_timedelta = False
@@ -998,7 +996,7 @@ def setitem(self, indexer, value):
998996
block = self.make_block(values)
999997
return block
1000998

1001-
def putmask(self, mask, new, axis: int = 0) -> List["Block"]:
999+
def putmask(self, mask, new) -> List["Block"]:
10021000
"""
10031001
putmask the data to the block; it is possible that we may create a
10041002
new dtype of block
@@ -1009,7 +1007,6 @@ def putmask(self, mask, new, axis: int = 0) -> List["Block"]:
10091007
----------
10101008
mask : np.ndarray[bool], SparseArray[bool], or BooleanArray
10111009
new : a ndarray/object
1012-
axis : int
10131010
10141011
Returns
10151012
-------
@@ -1026,8 +1023,6 @@ def putmask(self, mask, new, axis: int = 0) -> List["Block"]:
10261023
new = self.fill_value
10271024

10281025
if self._can_hold_element(new):
1029-
# We only get here for non-Extension Blocks, so _try_coerce_args
1030-
# is only relevant for DatetimeBlock and TimedeltaBlock
10311026
if self.dtype.kind in ["m", "M"]:
10321027
arr = self.array_values()
10331028
arr = cast("NDArrayBackedExtensionArray", arr)
@@ -1040,14 +1035,17 @@ def putmask(self, mask, new, axis: int = 0) -> List["Block"]:
10401035
new_values = new_values.T
10411036

10421037
putmask_without_repeat(new_values, mask, new)
1038+
return [self]
1039+
1040+
elif not mask.any():
1041+
return [self]
10431042

1044-
# maybe upcast me
1045-
elif mask.any():
1043+
else:
1044+
# may need to upcast
10461045
if transpose:
10471046
mask = mask.T
10481047
if isinstance(new, np.ndarray):
10491048
new = new.T
1050-
axis = new_values.ndim - axis - 1
10511049

10521050
# operate column-by-column
10531051
def f(mask, val, idx):
@@ -1074,8 +1072,6 @@ def f(mask, val, idx):
10741072
new_blocks = self.split_and_operate(mask, f, True)
10751073
return new_blocks
10761074

1077-
return [self]
1078-
10791075
def coerce_to_target_dtype(self, other):
10801076
"""
10811077
coerce the current block to a dtype compat for other
@@ -1195,7 +1191,7 @@ def _interpolate(
11951191

11961192
# only deal with floats
11971193
if not self.is_float:
1198-
if not self.is_integer:
1194+
if self.dtype.kind not in ["i", "u"]:
11991195
return [self]
12001196
data = data.astype(np.float64)
12011197

@@ -1316,7 +1312,7 @@ def where(self, other, cond, errors="raise", axis: int = 0) -> List["Block"]:
13161312
# see if we can operate on the entire block, or need item-by-item
13171313
# or if we are a single block (ndim == 1)
13181314
if (
1319-
(self.is_integer or self.is_bool)
1315+
(self.dtype.kind in ["b", "i", "u"])
13201316
and lib.is_float(other)
13211317
and np.isnan(other)
13221318
):
@@ -1332,7 +1328,7 @@ def where(self, other, cond, errors="raise", axis: int = 0) -> List["Block"]:
13321328
return self._maybe_downcast(blocks, "infer")
13331329

13341330
if not (
1335-
(self.is_integer or self.is_bool)
1331+
(self.dtype.kind in ["b", "i", "u"])
13361332
and lib.is_float(other)
13371333
and np.isnan(other)
13381334
):
@@ -1577,7 +1573,7 @@ def set_inplace(self, locs, values):
15771573
assert locs.tolist() == [0]
15781574
self.values = values
15791575

1580-
def putmask(self, mask, new, axis: int = 0) -> List["Block"]:
1576+
def putmask(self, mask, new) -> List["Block"]:
15811577
"""
15821578
See Block.putmask.__doc__
15831579
"""
@@ -1912,11 +1908,18 @@ def external_values(self):
19121908
class NumericBlock(Block):
19131909
__slots__ = ()
19141910
is_numeric = True
1915-
_can_hold_na = True
19161911

19171912
def _can_hold_element(self, element: Any) -> bool:
19181913
return can_hold_element(self.dtype, element)
19191914

1915+
@property
1916+
def _can_hold_na(self):
1917+
return self.dtype.kind not in ["b", "i", "u"]
1918+
1919+
@property
1920+
def is_bool(self):
1921+
return self.dtype.kind == "b"
1922+
19201923

19211924
class FloatBlock(NumericBlock):
19221925
__slots__ = ()
@@ -1956,17 +1959,6 @@ def to_native_types(
19561959
return self.make_block(res)
19571960

19581961

1959-
class ComplexBlock(NumericBlock):
1960-
__slots__ = ()
1961-
is_complex = True
1962-
1963-
1964-
class IntBlock(NumericBlock):
1965-
__slots__ = ()
1966-
is_integer = True
1967-
_can_hold_na = False
1968-
1969-
19701962
class DatetimeLikeBlockMixin(HybridMixin, Block):
19711963
"""Mixin class for DatetimeBlock, DatetimeTZBlock, and TimedeltaBlock."""
19721964

@@ -2232,7 +2224,7 @@ def _check_ndim(self, values, ndim):
22322224
return ndim
22332225

22342226

2235-
class TimeDeltaBlock(DatetimeLikeBlockMixin, IntBlock):
2227+
class TimeDeltaBlock(DatetimeLikeBlockMixin):
22362228
__slots__ = ()
22372229
is_timedelta = True
22382230
_can_hold_na = True
@@ -2269,12 +2261,6 @@ def fillna(self, value, **kwargs):
22692261
return super().fillna(value, **kwargs)
22702262

22712263

2272-
class BoolBlock(NumericBlock):
2273-
__slots__ = ()
2274-
is_bool = True
2275-
_can_hold_na = False
2276-
2277-
22782264
class ObjectBlock(Block):
22792265
__slots__ = ()
22802266
is_object = True
@@ -2477,12 +2463,8 @@ def get_block_type(values, dtype: Optional[Dtype] = None):
24772463
cls = TimeDeltaBlock
24782464
elif kind == "f":
24792465
cls = FloatBlock
2480-
elif kind == "c":
2481-
cls = ComplexBlock
2482-
elif kind == "i" or kind == "u":
2483-
cls = IntBlock
2484-
elif kind == "b":
2485-
cls = BoolBlock
2466+
elif kind in ["c", "i", "u", "b"]:
2467+
cls = NumericBlock
24862468
else:
24872469
cls = ObjectBlock
24882470
return cls

0 commit comments

Comments
 (0)