Skip to content

Commit 811b9d0

Browse files
committed
Merge branch 'master' of https://github.com/pandas-dev/pandas into ci-files-3
2 parents 6119a92 + 3989493 commit 811b9d0

File tree

21 files changed

+120
-263
lines changed

21 files changed

+120
-263
lines changed

doc/source/whatsnew/v1.1.1.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ Fixed regressions
1616
~~~~~~~~~~~~~~~~~
1717

1818
- Fixed regression where :meth:`DataFrame.to_numpy` would raise a ``RuntimeError`` for mixed dtypes when converting to ``str`` (:issue:`35455`)
19-
- Fixed regression where :func:`read_csv` would raise a ``ValueError`` when ``pandas.options.mode.use_inf_as_na`` was set to ``True`` (:issue:`35493`).
19+
- Fixed regression where :func:`read_csv` would raise a ``ValueError`` when ``pandas.options.mode.use_inf_as_na`` was set to ``True`` (:issue:`35493`)
2020
- Fixed regression where :func:`pandas.testing.assert_series_equal` would raise an error when non-numeric dtypes were passed with ``check_exact=True`` (:issue:`35446`)
2121
- Fixed regression in :class:`pandas.core.groupby.RollingGroupby` where column selection was ignored (:issue:`35486`)
2222
- Fixed regression in :meth:`DataFrame.shift` with ``axis=1`` and heterogeneous dtypes (:issue:`35488`)
23+
- Fixed regression in :meth:`DataFrame.diff` with read-only data (:issue:`35559`)
2324
- Fixed regression in ``.groupby(..).rolling(..)`` where a segfault would occur with ``center=True`` and an odd number of values (:issue:`35552`)
2425
- Fixed regression in :meth:`DataFrame.apply` where functions that altered the input in-place only operated on a single row (:issue:`35462`)
26+
- Fixed regression in :meth:`DataFrame.reset_index` would raise a ``ValueError`` on empty :class:`DataFrame` with a :class:`MultiIndex` with a ``datetime64`` dtype level (:issue:`35606`, :issue:`35657`)
2527
- Fixed regression where :meth:`DataFrame.merge_asof` would raise a ``UnboundLocalError`` when ``left_index`` , ``right_index`` and ``tolerance`` were set (:issue:`35558`)
2628
- Fixed regression in ``.groupby(..).rolling(..)`` where a custom ``BaseIndexer`` would be ignored (:issue:`35557`)
2729

@@ -32,7 +34,7 @@ Fixed regressions
3234
Bug fixes
3335
~~~~~~~~~
3436

35-
- Bug in ``Styler`` whereby `cell_ids` argument had no effect due to other recent changes (:issue:`35588`).
37+
- Bug in ``Styler`` whereby `cell_ids` argument had no effect due to other recent changes (:issue:`35588`) (:issue:`35663`).
3638

3739
Categorical
3840
^^^^^^^^^^^

doc/source/whatsnew/v1.2.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ Datetimelike
172172
^^^^^^^^^^^^
173173
- Bug in :attr:`DatetimeArray.date` where a ``ValueError`` would be raised with a read-only backing array (:issue:`33530`)
174174
- Bug in ``NaT`` comparisons failing to raise ``TypeError`` on invalid inequality comparisons (:issue:`35046`)
175+
- Bug in :class:`DateOffset` where attributes reconstructed from pickle files differ from original objects when input values exceed normal ranges (e.g months=12) (:issue:`34511`)
175176
-
176177

177178
Timedelta

pandas/_config/localization.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,14 @@ def _valid_locales(locales, normalize):
8888
valid_locales : list
8989
A list of valid locales.
9090
"""
91-
if normalize:
92-
normalizer = lambda x: locale.normalize(x.strip())
93-
else:
94-
normalizer = lambda x: x.strip()
95-
96-
return list(filter(can_set_locale, map(normalizer, locales)))
91+
return [
92+
loc
93+
for loc in (
94+
locale.normalize(loc.strip()) if normalize else loc.strip()
95+
for loc in locales
96+
)
97+
if can_set_locale(loc)
98+
]
9799

98100

99101
def _default_locale_getter():

pandas/_libs/algos.pyx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,14 +1200,15 @@ ctypedef fused out_t:
12001200
@cython.boundscheck(False)
12011201
@cython.wraparound(False)
12021202
def diff_2d(
1203-
diff_t[:, :] arr,
1204-
out_t[:, :] out,
1203+
ndarray[diff_t, ndim=2] arr, # TODO(cython 3) update to "const diff_t[:, :] arr"
1204+
ndarray[out_t, ndim=2] out,
12051205
Py_ssize_t periods,
12061206
int axis,
12071207
):
12081208
cdef:
12091209
Py_ssize_t i, j, sx, sy, start, stop
1210-
bint f_contig = arr.is_f_contig()
1210+
bint f_contig = arr.flags.f_contiguous
1211+
# bint f_contig = arr.is_f_contig() # TODO(cython 3)
12111212

12121213
# Disable for unsupported dtype combinations,
12131214
# see https://github.com/cython/cython/issues/2646

pandas/_libs/tslibs/offsets.pyx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -989,13 +989,6 @@ cdef class RelativeDeltaOffset(BaseOffset):
989989
state["_offset"] = state.pop("offset")
990990
state["kwds"]["offset"] = state["_offset"]
991991

992-
if "_offset" in state and not isinstance(state["_offset"], timedelta):
993-
# relativedelta, we need to populate using its kwds
994-
offset = state["_offset"]
995-
odict = offset.__dict__
996-
kwds = {key: odict[key] for key in odict if odict[key]}
997-
state.update(kwds)
998-
999992
self.n = state.pop("n")
1000993
self.normalize = state.pop("normalize")
1001994
self._cache = state.pop("_cache", {})

pandas/core/computation/expr.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,9 @@ def _is_type(t):
167167

168168
# partition all AST nodes
169169
_all_nodes = frozenset(
170-
filter(
171-
lambda x: isinstance(x, type) and issubclass(x, ast.AST),
172-
(getattr(ast, node) for node in dir(ast)),
173-
)
170+
node
171+
for node in (getattr(ast, name) for name in dir(ast))
172+
if isinstance(node, type) and issubclass(node, ast.AST)
174173
)
175174

176175

pandas/core/frame.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4816,7 +4816,7 @@ def _maybe_casted_values(index, labels=None):
48164816

48174817
# we can have situations where the whole mask is -1,
48184818
# meaning there is nothing found in labels, so make all nan's
4819-
if mask.all():
4819+
if mask.size > 0 and mask.all():
48204820
dtype = index.dtype
48214821
fill_value = na_value_for_dtype(dtype)
48224822
values = construct_1d_arraylike_from_scalar(

pandas/core/reshape/merge.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,8 +2012,11 @@ def _sort_labels(uniques: np.ndarray, left, right):
20122012
def _get_join_keys(llab, rlab, shape, sort: bool):
20132013

20142014
# how many levels can be done without overflow
2015-
pred = lambda i: not is_int64_overflow_possible(shape[:i])
2016-
nlev = next(filter(pred, range(len(shape), 0, -1)))
2015+
nlev = next(
2016+
lev
2017+
for lev in range(len(shape), 0, -1)
2018+
if not is_int64_overflow_possible(shape[:lev])
2019+
)
20172020

20182021
# get keys for the first `nlev` levels
20192022
stride = np.prod(shape[1:nlev], dtype="i8")

pandas/io/formats/style.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -390,16 +390,16 @@ def format_attr(pair):
390390
"is_visible": (c not in hidden_columns),
391391
}
392392
# only add an id if the cell has a style
393+
props = []
393394
if self.cell_ids or (r, c) in ctx:
394395
row_dict["id"] = "_".join(cs[1:])
396+
for x in ctx[r, c]:
397+
# have to handle empty styles like ['']
398+
if x.count(":"):
399+
props.append(tuple(x.split(":")))
400+
else:
401+
props.append(("", ""))
395402
row_es.append(row_dict)
396-
props = []
397-
for x in ctx[r, c]:
398-
# have to handle empty styles like ['']
399-
if x.count(":"):
400-
props.append(tuple(x.split(":")))
401-
else:
402-
props.append(("", ""))
403403
cellstyle_map[tuple(props)].append(f"row{r}_col{c}")
404404
body.append(row_es)
405405

pandas/io/json/_json.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,8 +765,9 @@ def _combine_lines(self, lines) -> str:
765765
"""
766766
Combines a list of JSON objects into one JSON object.
767767
"""
768-
lines = filter(None, map(lambda x: x.strip(), lines))
769-
return "[" + ",".join(lines) + "]"
768+
return (
769+
f'[{",".join((line for line in (line.strip() for line in lines) if line))}]'
770+
)
770771

771772
def read(self):
772773
"""

pandas/io/parsers.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,9 +2161,7 @@ def read(self, nrows=None):
21612161
if self.usecols is not None:
21622162
columns = self._filter_usecols(columns)
21632163

2164-
col_dict = dict(
2165-
filter(lambda item: item[0] in columns, col_dict.items())
2166-
)
2164+
col_dict = {k: v for k, v in col_dict.items() if k in columns}
21672165

21682166
return index, columns, col_dict
21692167

pandas/io/pytables.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,22 +99,20 @@ def _ensure_str(name):
9999

100100
def _ensure_term(where, scope_level: int):
101101
"""
102-
ensure that the where is a Term or a list of Term
103-
this makes sure that we are capturing the scope of variables
104-
that are passed
105-
create the terms here with a frame_level=2 (we are 2 levels down)
102+
Ensure that the where is a Term or a list of Term.
103+
104+
This makes sure that we are capturing the scope of variables that are
105+
passed create the terms here with a frame_level=2 (we are 2 levels down)
106106
"""
107107
# only consider list/tuple here as an ndarray is automatically a coordinate
108108
# list
109109
level = scope_level + 1
110110
if isinstance(where, (list, tuple)):
111-
wlist = []
112-
for w in filter(lambda x: x is not None, where):
113-
if not maybe_expression(w):
114-
wlist.append(w)
115-
else:
116-
wlist.append(Term(w, scope_level=level))
117-
where = wlist
111+
where = [
112+
Term(term, scope_level=level + 1) if maybe_expression(term) else term
113+
for term in where
114+
if term is not None
115+
]
118116
elif maybe_expression(where):
119117
where = Term(where, scope_level=level)
120118
return where if where is None or len(where) else None

pandas/tests/computation/test_eval.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def setup_ops(self):
168168
def setup_method(self, method):
169169
self.setup_ops()
170170
self.setup_data()
171-
self.current_engines = filter(lambda x: x != self.engine, _engines)
171+
self.current_engines = (engine for engine in _engines if engine != self.engine)
172172

173173
def teardown_method(self, method):
174174
del self.lhses, self.rhses, self.scalar_rhses, self.scalar_lhses
@@ -774,11 +774,9 @@ def setup_class(cls):
774774
cls.parser = "python"
775775

776776
def setup_ops(self):
777-
self.cmp_ops = list(
778-
filter(lambda x: x not in ("in", "not in"), expr._cmp_ops_syms)
779-
)
777+
self.cmp_ops = [op for op in expr._cmp_ops_syms if op not in ("in", "not in")]
780778
self.cmp2_ops = self.cmp_ops[::-1]
781-
self.bin_ops = [s for s in expr._bool_ops_syms if s not in ("and", "or")]
779+
self.bin_ops = [op for op in expr._bool_ops_syms if op not in ("and", "or")]
782780
self.special_case_ops = _special_case_arith_ops_syms
783781
self.arith_ops = _good_arith_ops
784782
self.unary_ops = "+", "-", "~"
@@ -1150,9 +1148,9 @@ def eval(self, *args, **kwargs):
11501148
return pd.eval(*args, **kwargs)
11511149

11521150
def test_simple_arith_ops(self):
1153-
ops = self.arith_ops
1151+
ops = (op for op in self.arith_ops if op != "//")
11541152

1155-
for op in filter(lambda x: x != "//", ops):
1153+
for op in ops:
11561154
ex = f"1 {op} 1"
11571155
ex2 = f"x {op} 1"
11581156
ex3 = f"1 {op} (x + 1)"
@@ -1637,8 +1635,11 @@ def setup_class(cls):
16371635
super().setup_class()
16381636
cls.engine = "numexpr"
16391637
cls.parser = "python"
1640-
cls.arith_ops = expr._arith_ops_syms + expr._cmp_ops_syms
1641-
cls.arith_ops = filter(lambda x: x not in ("in", "not in"), cls.arith_ops)
1638+
cls.arith_ops = [
1639+
op
1640+
for op in expr._arith_ops_syms + expr._cmp_ops_syms
1641+
if op not in ("in", "not in")
1642+
]
16421643

16431644
def test_check_many_exprs(self):
16441645
a = 1 # noqa
@@ -1726,8 +1727,11 @@ class TestOperationsPythonPython(TestOperationsNumExprPython):
17261727
def setup_class(cls):
17271728
super().setup_class()
17281729
cls.engine = cls.parser = "python"
1729-
cls.arith_ops = expr._arith_ops_syms + expr._cmp_ops_syms
1730-
cls.arith_ops = filter(lambda x: x not in ("in", "not in"), cls.arith_ops)
1730+
cls.arith_ops = [
1731+
op
1732+
for op in expr._arith_ops_syms + expr._cmp_ops_syms
1733+
if op not in ("in", "not in")
1734+
]
17311735

17321736

17331737
class TestOperationsPythonPandas(TestOperationsNumExprPandas):

pandas/tests/frame/methods/test_diff.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,12 @@ def test_diff_integer_na(self, axis, expected):
214214
# Test case for default behaviour of diff
215215
result = df.diff(axis=axis)
216216
tm.assert_frame_equal(result, expected)
217+
218+
def test_diff_readonly(self):
219+
# https://github.com/pandas-dev/pandas/issues/35559
220+
arr = np.random.randn(5, 2)
221+
arr.flags.writeable = False
222+
df = pd.DataFrame(arr)
223+
result = df.diff()
224+
expected = pd.DataFrame(np.array(df)).diff()
225+
tm.assert_frame_equal(result, expected)

pandas/tests/frame/methods/test_reset_index.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,33 @@ def test_reset_index_dtypes_on_empty_frame_with_multiindex(array, dtype):
318318
result = DataFrame(index=idx)[:0].reset_index().dtypes
319319
expected = Series({"level_0": np.int64, "level_1": np.float64, "level_2": dtype})
320320
tm.assert_series_equal(result, expected)
321+
322+
323+
def test_reset_index_empty_frame_with_datetime64_multiindex():
324+
# https://github.com/pandas-dev/pandas/issues/35606
325+
idx = MultiIndex(
326+
levels=[[pd.Timestamp("2020-07-20 00:00:00")], [3, 4]],
327+
codes=[[], []],
328+
names=["a", "b"],
329+
)
330+
df = DataFrame(index=idx, columns=["c", "d"])
331+
result = df.reset_index()
332+
expected = DataFrame(
333+
columns=list("abcd"), index=RangeIndex(start=0, stop=0, step=1)
334+
)
335+
expected["a"] = expected["a"].astype("datetime64[ns]")
336+
expected["b"] = expected["b"].astype("int64")
337+
tm.assert_frame_equal(result, expected)
338+
339+
340+
def test_reset_index_empty_frame_with_datetime64_multiindex_from_groupby():
341+
# https://github.com/pandas-dev/pandas/issues/35657
342+
df = DataFrame(dict(c1=[10.0], c2=["a"], c3=pd.to_datetime("2020-01-01")))
343+
df = df.head(0).groupby(["c2", "c3"])[["c1"]].sum()
344+
result = df.reset_index()
345+
expected = DataFrame(
346+
columns=["c2", "c3", "c1"], index=RangeIndex(start=0, stop=0, step=1)
347+
)
348+
expected["c3"] = expected["c3"].astype("datetime64[ns]")
349+
expected["c1"] = expected["c1"].astype("float64")
350+
tm.assert_frame_equal(result, expected)
Binary file not shown.

pandas/tests/io/formats/test_style.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1684,8 +1684,11 @@ def f(a, b, styler):
16841684

16851685
def test_no_cell_ids(self):
16861686
# GH 35588
1687+
# GH 35663
16871688
df = pd.DataFrame(data=[[0]])
1688-
s = Styler(df, uuid="_", cell_ids=False).render()
1689+
styler = Styler(df, uuid="_", cell_ids=False)
1690+
styler.render()
1691+
s = styler.render() # render twice to ensure ctx is not updated
16891692
assert s.find('<td class="data row0 col0" >') != -1
16901693

16911694

pandas/tests/io/generate_legacy_storage_files.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
in ~/pandas
77
88
. activate pandas_0.20.3
9-
cd ~/
9+
cd ~/pandas/pandas
1010
11-
$ python pandas/pandas/tests/io/generate_legacy_storage_files.py \
12-
pandas/pandas/tests/io/data/legacy_pickle/0.20.3/ pickle
11+
$ python -m tests.io.generate_legacy_storage_files \
12+
tests/io/data/legacy_pickle/0.20.3/ pickle
1313
1414
This script generates a storage file for the current arch, system,
1515
and python version
@@ -328,7 +328,7 @@ def write_legacy_pickles(output_dir):
328328
pth = f"{platform_name()}.pickle"
329329

330330
fh = open(os.path.join(output_dir, pth), "wb")
331-
pickle.dump(create_pickle_data(), fh, pickle.HIGHEST_PROTOCOL)
331+
pickle.dump(create_pickle_data(), fh, pickle.DEFAULT_PROTOCOL)
332332
fh.close()
333333

334334
print(f"created pickle file: {pth}")

0 commit comments

Comments
 (0)