Skip to content

Commit f4acbf9

Browse files
Merge branch 'master' into 16737-unexpected-results-creating-an-empty-series
2 parents 2109012 + cf61be6 commit f4acbf9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+514
-507
lines changed

ci/code_checks.sh

+7-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,13 @@ if [[ -z "$CHECK" || "$CHECK" == "patterns" ]]; then
150150
# Check for imports from pandas._testing instead of `import pandas._testing as tm`
151151
invgrep -R --include="*.py*" -E "from pandas._testing import" pandas/tests
152152
RET=$(($RET + $?)) ; echo $MSG "DONE"
153-
invgrep -R --include="*.py*" -E "from pandas.util import testing as tm" pandas/tests
153+
invgrep -R --include="*.py*" -E "from pandas import _testing as tm" pandas/tests
154+
RET=$(($RET + $?)) ; echo $MSG "DONE"
155+
156+
# No direct imports from conftest
157+
invgrep -R --include="*.py*" -E "conftest import" pandas/tests
158+
RET=$(($RET + $?)) ; echo $MSG "DONE"
159+
invgrep -R --include="*.py*" -E "import conftest" pandas/tests
154160
RET=$(($RET + $?)) ; echo $MSG "DONE"
155161

156162
MSG='Check for use of exec' ; echo $MSG

doc/source/user_guide/cookbook.rst

-27
Original file line numberDiff line numberDiff line change
@@ -1333,33 +1333,6 @@ Values can be set to NaT using np.nan, similar to datetime
13331333
y[1] = np.nan
13341334
y
13351335
1336-
Aliasing axis names
1337-
-------------------
1338-
1339-
To globally provide aliases for axis names, one can define these 2 functions:
1340-
1341-
.. ipython:: python
1342-
1343-
def set_axis_alias(cls, axis, alias):
1344-
if axis not in cls._AXIS_NUMBERS:
1345-
raise Exception("invalid axis [%s] for alias [%s]" % (axis, alias))
1346-
cls._AXIS_ALIASES[alias] = axis
1347-
1348-
.. ipython:: python
1349-
1350-
def clear_axis_alias(cls, axis, alias):
1351-
if axis not in cls._AXIS_NUMBERS:
1352-
raise Exception("invalid axis [%s] for alias [%s]" % (axis, alias))
1353-
cls._AXIS_ALIASES.pop(alias, None)
1354-
1355-
.. ipython:: python
1356-
1357-
set_axis_alias(pd.DataFrame, 'columns', 'myaxis2')
1358-
df2 = pd.DataFrame(np.random.randn(3, 2), columns=['c1', 'c2'],
1359-
index=['i1', 'i2', 'i3'])
1360-
df2.sum(axis='myaxis2')
1361-
clear_axis_alias(pd.DataFrame, 'columns', 'myaxis2')
1362-
13631336
Creating example data
13641337
---------------------
13651338

doc/source/whatsnew/v1.1.0.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ Other API changes
175175
- :meth:`Groupby.groups` now returns an abbreviated representation when called on large dataframes (:issue:`1135`)
176176
- ``loc`` lookups with an object-dtype :class:`Index` and an integer key will now raise ``KeyError`` instead of ``TypeError`` when key is missing (:issue:`31905`)
177177
- Using a :func:`pandas.api.indexers.BaseIndexer` with ``skew``, ``cov``, ``corr`` will now raise a ``NotImplementedError`` (:issue:`32865`)
178-
- Using a :func:`pandas.api.indexers.BaseIndexer` with ``count``, ``min``, ``max`` will now return correct results for any monotonic :func:`pandas.api.indexers.BaseIndexer` descendant (:issue:`32865`)
178+
- Using a :func:`pandas.api.indexers.BaseIndexer` with ``count``, ``min``, ``max``, ``median`` will now return correct results for any monotonic :func:`pandas.api.indexers.BaseIndexer` descendant (:issue:`32865`)
179179
- Added a :func:`pandas.api.indexers.FixedForwardWindowIndexer` class to support forward-looking windows during ``rolling`` operations.
180180
-
181181

@@ -584,6 +584,8 @@ I/O
584584
- Bug in :func:`pandas.io.json.json_normalize` where location specified by `record_path` doesn't point to an array. (:issue:`26284`)
585585
- :func:`pandas.read_hdf` has a more explicit error message when loading an
586586
unsupported HDF file (:issue:`9539`)
587+
- Bug in :meth:`~DataFrame.to_parquet` was not raising ``PermissionError`` when writing to a private s3 bucket with invalid creds. (:issue:`27679`)
588+
- Bug in :meth:`~DataFrame.to_csv` was silently failing when writing to an invalid s3 bucket. (:issue:`32486`)
587589

588590
Plotting
589591
^^^^^^^^

pandas/_libs/window/aggregations.pyx

+3-2
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,8 @@ def roll_kurt_variable(ndarray[float64_t] values, ndarray[int64_t] start,
843843

844844

845845
def roll_median_c(ndarray[float64_t] values, ndarray[int64_t] start,
846-
ndarray[int64_t] end, int64_t minp, int64_t win):
846+
ndarray[int64_t] end, int64_t minp, int64_t win=0):
847+
# GH 32865. win argument kept for compatibility
847848
cdef:
848849
float64_t val, res, prev
849850
bint err = False
@@ -858,7 +859,7 @@ def roll_median_c(ndarray[float64_t] values, ndarray[int64_t] start,
858859
# actual skiplist ops outweigh any window computation costs
859860
output = np.empty(N, dtype=float)
860861

861-
if win == 0 or (end - start).max() == 0:
862+
if (end - start).max() == 0:
862863
output[:] = NaN
863864
return output
864865
win = (end - start).max()

pandas/core/array_algos/transforms.py

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
def shift(values: np.ndarray, periods: int, axis: int, fill_value) -> np.ndarray:
1111
new_values = values
1212

13+
if periods == 0:
14+
# TODO: should we copy here?
15+
return new_values
16+
1317
# make sure array sent to np.roll is c_contiguous
1418
f_ordered = values.flags.f_contiguous
1519
if f_ordered:

pandas/core/arrays/categorical.py

+49-55
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
from pandas.core.dtypes.common import (
2828
ensure_int64,
2929
ensure_object,
30-
ensure_platform_int,
3130
is_categorical_dtype,
3231
is_datetime64_dtype,
3332
is_dict_like,
@@ -51,6 +50,7 @@
5150
from pandas.core.accessor import PandasDelegate, delegate_names
5251
import pandas.core.algorithms as algorithms
5352
from pandas.core.algorithms import _get_data_algo, factorize, take, take_1d, unique1d
53+
from pandas.core.array_algos.transforms import shift
5454
from pandas.core.arrays.base import ExtensionArray, _extension_array_shared_docs
5555
from pandas.core.base import NoNewAttributesMixin, PandasObject, _shared_docs
5656
import pandas.core.common as com
@@ -199,17 +199,6 @@ def contains(cat, key, container):
199199
return any(loc_ in container for loc_ in loc)
200200

201201

202-
_codes_doc = """
203-
The category codes of this categorical.
204-
205-
Level codes are an array if integer which are the positions of the real
206-
values in the categories array.
207-
208-
There is not setter, use the other categorical methods and the normal item
209-
setter to change values in the categorical.
210-
"""
211-
212-
213202
class Categorical(ExtensionArray, PandasObject):
214203
"""
215204
Represent a categorical variable in classic R / S-plus fashion.
@@ -652,27 +641,26 @@ def from_codes(cls, codes, categories=None, ordered=None, dtype=None):
652641

653642
return cls(codes, dtype=dtype, fastpath=True)
654643

655-
def _get_codes(self):
644+
@property
645+
def codes(self) -> np.ndarray:
656646
"""
657-
Get the codes.
647+
The category codes of this categorical.
648+
649+
Codes are an array of integers which are the positions of the actual
650+
values in the categories array.
651+
652+
There is no setter, use the other categorical methods and the normal item
653+
setter to change values in the categorical.
658654
659655
Returns
660656
-------
661-
codes : integer array view
662-
A non writable view of the `codes` array.
657+
ndarray[int]
658+
A non-writable view of the `codes` array.
663659
"""
664660
v = self._codes.view()
665661
v.flags.writeable = False
666662
return v
667663

668-
def _set_codes(self, codes):
669-
"""
670-
Not settable by the user directly
671-
"""
672-
raise ValueError("cannot set Categorical codes directly")
673-
674-
codes = property(fget=_get_codes, fset=_set_codes, doc=_codes_doc)
675-
676664
def _set_categories(self, categories, fastpath=False):
677665
"""
678666
Sets new categories inplace
@@ -1241,23 +1229,41 @@ def shift(self, periods, fill_value=None):
12411229
codes = self.codes
12421230
if codes.ndim > 1:
12431231
raise NotImplementedError("Categorical with ndim > 1.")
1244-
if np.prod(codes.shape) and (periods != 0):
1245-
codes = np.roll(codes, ensure_platform_int(periods), axis=0)
1246-
if isna(fill_value):
1247-
fill_value = -1
1248-
elif fill_value in self.categories:
1249-
fill_value = self.categories.get_loc(fill_value)
1250-
else:
1251-
raise ValueError(
1252-
f"'fill_value={fill_value}' is not present "
1253-
"in this Categorical's categories"
1254-
)
1255-
if periods > 0:
1256-
codes[:periods] = fill_value
1257-
else:
1258-
codes[periods:] = fill_value
12591232

1260-
return self.from_codes(codes, dtype=self.dtype)
1233+
fill_value = self._validate_fill_value(fill_value)
1234+
1235+
codes = shift(codes.copy(), periods, axis=0, fill_value=fill_value)
1236+
1237+
return self._constructor(codes, dtype=self.dtype, fastpath=True)
1238+
1239+
def _validate_fill_value(self, fill_value):
1240+
"""
1241+
Convert a user-facing fill_value to a representation to use with our
1242+
underlying ndarray, raising ValueError if this is not possible.
1243+
1244+
Parameters
1245+
----------
1246+
fill_value : object
1247+
1248+
Returns
1249+
-------
1250+
fill_value : int
1251+
1252+
Raises
1253+
------
1254+
ValueError
1255+
"""
1256+
1257+
if isna(fill_value):
1258+
fill_value = -1
1259+
elif fill_value in self.categories:
1260+
fill_value = self.categories.get_loc(fill_value)
1261+
else:
1262+
raise ValueError(
1263+
f"'fill_value={fill_value}' is not present "
1264+
"in this Categorical's categories"
1265+
)
1266+
return fill_value
12611267

12621268
def __array__(self, dtype=None) -> np.ndarray:
12631269
"""
@@ -1835,24 +1841,12 @@ def take(self, indexer, allow_fill: bool = False, fill_value=None):
18351841
"""
18361842
indexer = np.asarray(indexer, dtype=np.intp)
18371843

1838-
dtype = self.dtype
1839-
1840-
if isna(fill_value):
1841-
fill_value = -1
1842-
elif allow_fill:
1844+
if allow_fill:
18431845
# convert user-provided `fill_value` to codes
1844-
if fill_value in self.categories:
1845-
fill_value = self.categories.get_loc(fill_value)
1846-
else:
1847-
msg = (
1848-
f"'fill_value' ('{fill_value}') is not in this "
1849-
"Categorical's categories."
1850-
)
1851-
raise TypeError(msg)
1846+
fill_value = self._validate_fill_value(fill_value)
18521847

18531848
codes = take(self._codes, indexer, allow_fill=allow_fill, fill_value=fill_value)
1854-
result = type(self).from_codes(codes, dtype=dtype)
1855-
return result
1849+
return self._constructor(codes, dtype=self.dtype, fastpath=True)
18561850

18571851
def take_nd(self, indexer, allow_fill: bool = False, fill_value=None):
18581852
# GH#27745 deprecate alias that other EAs dont have

0 commit comments

Comments
 (0)