Skip to content

Commit 1e46304

Browse files
authored
Merge branch 'master' into test_getmembers_series
2 parents 0a51ce0 + e752928 commit 1e46304

File tree

10 files changed

+121
-99
lines changed

10 files changed

+121
-99
lines changed

doc/source/user_guide/10min.rst

+4-4
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ The :meth:`~plt.close` method is used to `close <https://matplotlib.org/3.1.1/ap
730730
ts = ts.cumsum()
731731
732732
@savefig series_plot_basic.png
733-
ts.plot()
733+
ts.plot();
734734
735735
On a DataFrame, the :meth:`~DataFrame.plot` method is a convenience to plot all
736736
of the columns with labels:
@@ -743,10 +743,10 @@ of the columns with labels:
743743
744744
df = df.cumsum()
745745
746-
plt.figure()
747-
df.plot()
746+
plt.figure();
747+
df.plot();
748748
@savefig frame_plot_basic.png
749-
plt.legend(loc='best')
749+
plt.legend(loc='best');
750750
751751
Getting data in/out
752752
-------------------

doc/source/whatsnew/v1.2.1.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ I/O
4141

4242
Other
4343
~~~~~
44-
- - ``inspect.getmembers(Series)`` no longer raises an ``AbstractMethodError`` (:issue:`38782`).
44+
- ``inspect.getmembers(Series)`` no longer raises an ``AbstractMethodError`` (:issue:`38782`).
45+
- Fixed build failure on MacOS 11 in Python 3.9.1 (:issue:`38766`)
4546
-
4647

4748
.. ---------------------------------------------------------------------------

doc/source/whatsnew/v1.3.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ Sparse
295295

296296
ExtensionArray
297297
^^^^^^^^^^^^^^
298-
298+
- Bug in :meth:`DataFrame.where` when ``other`` is a :class:`Series` with ExtensionArray dtype (:issue:`38729`)
299299
-
300300
-
301301

pandas/_libs/window/aggregations.pyx

+9-39
Original file line numberDiff line numberDiff line change
@@ -55,39 +55,11 @@ cdef:
5555

5656
float64_t NaN = <float64_t>np.NaN
5757

58-
cdef inline int int_max(int a, int b): return a if a >= b else b
59-
cdef inline int int_min(int a, int b): return a if a <= b else b
60-
6158
cdef bint is_monotonic_increasing_start_end_bounds(
6259
ndarray[int64_t, ndim=1] start, ndarray[int64_t, ndim=1] end
6360
):
6461
return is_monotonic(start, False)[0] and is_monotonic(end, False)[0]
6562

66-
# Cython implementations of rolling sum, mean, variance, skewness,
67-
# other statistical moment functions
68-
#
69-
# Misc implementation notes
70-
# -------------------------
71-
#
72-
# - In Cython x * x is faster than x ** 2 for C types, this should be
73-
# periodically revisited to see if it's still true.
74-
#
75-
76-
# original C implementation by N. Devillard.
77-
# This code in public domain.
78-
# Function : kth_smallest()
79-
# In : array of elements, # of elements in the array, rank k
80-
# Out : one element
81-
# Job : find the kth smallest element in the array
82-
83-
# Reference:
84-
85-
# Author: Wirth, Niklaus
86-
# Title: Algorithms + data structures = programs
87-
# Publisher: Englewood Cliffs: Prentice-Hall, 1976
88-
# Physical description: 366 p.
89-
# Series: Prentice-Hall Series in Automatic Computation
90-
9163
# ----------------------------------------------------------------------
9264
# Rolling sum
9365

@@ -774,7 +746,6 @@ def roll_kurt(ndarray[float64_t] values, ndarray[int64_t] start,
774746

775747
def roll_median_c(const float64_t[:] values, ndarray[int64_t] start,
776748
ndarray[int64_t] end, int64_t minp):
777-
# GH 32865. win argument kept for compatibility
778749
cdef:
779750
float64_t val, res, prev
780751
bint err = False
@@ -1167,9 +1138,8 @@ def roll_apply(object obj,
11671138
arr = np.asarray(obj)
11681139

11691140
# ndarray input
1170-
if raw:
1171-
if not arr.flags.c_contiguous:
1172-
arr = arr.copy('C')
1141+
if raw and not arr.flags.c_contiguous:
1142+
arr = arr.copy('C')
11731143

11741144
counts = roll_sum(np.isfinite(arr).astype(float), start, end, minp)
11751145

@@ -1195,17 +1165,17 @@ def roll_apply(object obj,
11951165
# Rolling sum and mean for weighted window
11961166

11971167

1198-
def roll_weighted_sum(float64_t[:] values, float64_t[:] weights, int minp):
1168+
def roll_weighted_sum(const float64_t[:] values, const float64_t[:] weights, int minp):
11991169
return _roll_weighted_sum_mean(values, weights, minp, avg=0)
12001170

12011171

1202-
def roll_weighted_mean(float64_t[:] values, float64_t[:] weights, int minp):
1172+
def roll_weighted_mean(const float64_t[:] values, const float64_t[:] weights, int minp):
12031173
return _roll_weighted_sum_mean(values, weights, minp, avg=1)
12041174

12051175

1206-
cdef ndarray[float64_t] _roll_weighted_sum_mean(float64_t[:] values,
1207-
float64_t[:] weights,
1208-
int minp, bint avg):
1176+
cdef float64_t[:] _roll_weighted_sum_mean(const float64_t[:] values,
1177+
const float64_t[:] weights,
1178+
int minp, bint avg):
12091179
"""
12101180
Assume len(weights) << len(values)
12111181
"""
@@ -1270,7 +1240,7 @@ cdef ndarray[float64_t] _roll_weighted_sum_mean(float64_t[:] values,
12701240
if c < minp:
12711241
output[in_i] = NaN
12721242

1273-
return np.asarray(output)
1243+
return output
12741244

12751245

12761246
# ----------------------------------------------------------------------
@@ -1424,7 +1394,7 @@ cdef inline void remove_weighted_var(float64_t val,
14241394
mean[0] = 0
14251395

14261396

1427-
def roll_weighted_var(float64_t[:] values, float64_t[:] weights,
1397+
def roll_weighted_var(const float64_t[:] values, const float64_t[:] weights,
14281398
int64_t minp, unsigned int ddof):
14291399
"""
14301400
Calculates weighted rolling variance using West's online algorithm.

pandas/core/generic.py

+30-9
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@
8989
import pandas as pd
9090
from pandas.core import arraylike, indexing, missing, nanops
9191
import pandas.core.algorithms as algos
92+
from pandas.core.arrays import ExtensionArray
9293
from pandas.core.base import PandasObject, SelectionMixin
9394
import pandas.core.common as com
94-
from pandas.core.construction import create_series_with_explicit_dtype
95+
from pandas.core.construction import create_series_with_explicit_dtype, extract_array
9596
from pandas.core.flags import Flags
9697
from pandas.core.indexes import base as ibase
9798
from pandas.core.indexes.api import (
@@ -8780,6 +8781,9 @@ def _where(
87808781
"""
87818782
inplace = validate_bool_kwarg(inplace, "inplace")
87828783

8784+
if axis is not None:
8785+
axis = self._get_axis_number(axis)
8786+
87838787
# align the cond to same shape as myself
87848788
cond = com.apply_if_callable(cond, self)
87858789
if isinstance(cond, NDFrame):
@@ -8819,22 +8823,39 @@ def _where(
88198823
if other.ndim <= self.ndim:
88208824

88218825
_, other = self.align(
8822-
other, join="left", axis=axis, level=level, fill_value=np.nan
8826+
other,
8827+
join="left",
8828+
axis=axis,
8829+
level=level,
8830+
fill_value=np.nan,
8831+
copy=False,
88238832
)
88248833

88258834
# if we are NOT aligned, raise as we cannot where index
8826-
if axis is None and not all(
8827-
other._get_axis(i).equals(ax) for i, ax in enumerate(self.axes)
8828-
):
8835+
if axis is None and not other._indexed_same(self):
88298836
raise InvalidIndexError
88308837

8838+
elif other.ndim < self.ndim:
8839+
# TODO(EA2D): avoid object-dtype cast in EA case GH#38729
8840+
other = other._values
8841+
if axis == 0:
8842+
other = np.reshape(other, (-1, 1))
8843+
elif axis == 1:
8844+
other = np.reshape(other, (1, -1))
8845+
8846+
other = np.broadcast_to(other, self.shape)
8847+
88318848
# slice me out of the other
88328849
else:
88338850
raise NotImplementedError(
88348851
"cannot align with a higher dimensional NDFrame"
88358852
)
88368853

8837-
if isinstance(other, np.ndarray):
8854+
if not isinstance(other, (MultiIndex, NDFrame)):
8855+
# mainly just catching Index here
8856+
other = extract_array(other, extract_numpy=True)
8857+
8858+
if isinstance(other, (np.ndarray, ExtensionArray)):
88388859

88398860
if other.shape != self.shape:
88408861

@@ -8879,10 +8900,10 @@ def _where(
88798900
else:
88808901
align = self._get_axis_number(axis) == 1
88818902

8882-
if align and isinstance(other, NDFrame):
8883-
other = other.reindex(self._info_axis, axis=self._info_axis_number)
88848903
if isinstance(cond, NDFrame):
8885-
cond = cond.reindex(self._info_axis, axis=self._info_axis_number)
8904+
cond = cond.reindex(
8905+
self._info_axis, axis=self._info_axis_number, copy=False
8906+
)
88868907

88878908
block_axis = self._get_block_manager_axis(axis)
88888909

pandas/core/internals/blocks.py

+1-10
Original file line numberDiff line numberDiff line change
@@ -1064,9 +1064,7 @@ def putmask(self, mask, new, axis: int = 0) -> List["Block"]:
10641064
# If the default repeat behavior in np.putmask would go in the
10651065
# wrong direction, then explicitly repeat and reshape new instead
10661066
if getattr(new, "ndim", 0) >= 1:
1067-
if self.ndim - 1 == new.ndim and axis == 1:
1068-
new = np.repeat(new, new_values.shape[-1]).reshape(self.shape)
1069-
new = new.astype(new_values.dtype)
1067+
new = new.astype(new_values.dtype, copy=False)
10701068

10711069
# we require exact matches between the len of the
10721070
# values we are setting (or is compat). np.putmask
@@ -1104,13 +1102,6 @@ def putmask(self, mask, new, axis: int = 0) -> List["Block"]:
11041102
new = new.T
11051103
axis = new_values.ndim - axis - 1
11061104

1107-
# Pseudo-broadcast
1108-
if getattr(new, "ndim", 0) >= 1:
1109-
if self.ndim - 1 == new.ndim:
1110-
new_shape = list(new.shape)
1111-
new_shape.insert(axis, 1)
1112-
new = new.reshape(tuple(new_shape))
1113-
11141105
# operate column-by-column
11151106
def f(mask, val, idx):
11161107

pandas/core/window/rolling.py

+7-13
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,8 @@ def _create_data(self, obj: FrameOrSeries) -> FrameOrSeries:
174174
Split data into blocks & return conformed data.
175175
"""
176176
# filter out the on from the object
177-
if self.on is not None and not isinstance(self.on, Index):
178-
if obj.ndim == 2:
179-
obj = obj.reindex(columns=obj.columns.difference([self.on]), copy=False)
177+
if self.on is not None and not isinstance(self.on, Index) and obj.ndim == 2:
178+
obj = obj.reindex(columns=obj.columns.difference([self.on]), copy=False)
180179
if self.axis == 1:
181180
# GH: 20649 in case of mixed dtype and axis=1 we have to convert everything
182181
# to float to calculate the complete row at once. We exclude all non-numeric
@@ -238,10 +237,6 @@ def _get_cov_corr_window(
238237
"""
239238
return self.window
240239

241-
@property
242-
def _window_type(self) -> str:
243-
return type(self).__name__
244-
245240
def __repr__(self) -> str:
246241
"""
247242
Provide a nice str repr of our rolling object.
@@ -252,7 +247,7 @@ def __repr__(self) -> str:
252247
if getattr(self, attr_name, None) is not None
253248
)
254249
attrs = ",".join(attrs_list)
255-
return f"{self._window_type} [{attrs}]"
250+
return f"{type(self).__name__} [{attrs}]"
256251

257252
def __iter__(self):
258253
obj = self._create_data(self._selected_obj)
@@ -278,7 +273,7 @@ def _prep_values(self, values: Optional[np.ndarray] = None) -> np.ndarray:
278273

279274
if needs_i8_conversion(values.dtype):
280275
raise NotImplementedError(
281-
f"ops for {self._window_type} for this "
276+
f"ops for {type(self).__name__} for this "
282277
f"dtype {values.dtype} are not implemented"
283278
)
284279
else:
@@ -464,7 +459,6 @@ def calc(x):
464459
result = np.apply_along_axis(calc, self.axis, values)
465460
else:
466461
result = calc(values)
467-
result = np.asarray(result)
468462

469463
if numba_cache_key is not None:
470464
NUMBA_FUNC_CACHE[numba_cache_key] = func
@@ -1102,8 +1096,8 @@ def calc(x):
11021096
if values.ndim > 1:
11031097
result = np.apply_along_axis(calc, self.axis, values)
11041098
else:
1105-
result = calc(values)
1106-
result = np.asarray(result)
1099+
# Our weighted aggregations return memoryviews
1100+
result = np.asarray(calc(values))
11071101

11081102
if self.center:
11091103
result = self._center_window(result, offset)
@@ -2158,7 +2152,7 @@ def _validate_monotonic(self):
21582152
"""
21592153
Validate that on is monotonic;
21602154
in this case we have to check only for nans, because
2161-
monotonicy was already validated at a higher level.
2155+
monotonicity was already validated at a higher level.
21622156
"""
21632157
if self._on.hasnans:
21642158
self._raise_monotonic_error()

0 commit comments

Comments
 (0)