Skip to content

Commit d625b5b

Browse files
committed
Merge remote-tracking branch 'upstream/master' into bug/groupby_rolling_multiindex
2 parents e85e494 + 52b8459 commit d625b5b

File tree

6 files changed

+60
-5
lines changed

6 files changed

+60
-5
lines changed

doc/source/whatsnew/v1.2.4.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Fixed regressions
1717

1818
- Fixed regression in :meth:`DataFrame.sum` when ``min_count`` greater than the :class:`DataFrame` shape was passed resulted in a ``ValueError`` (:issue:`39738`)
1919
- Fixed regression in :meth:`DataFrame.to_json` raising ``AttributeError`` when run on PyPy (:issue:`39837`)
20+
- Fixed regression in (in)equality comparison of ``pd.NaT`` with a non-datetimelike numpy array returning a scalar instead of an array (:issue:`40722`)
2021
- Fixed regression in :meth:`DataFrame.where` not returning a copy in the case of an all True condition (:issue:`39595`)
2122
- Fixed regression in :meth:`DataFrame.replace` raising ``IndexError`` when ``regex`` was a multi-key dictionary (:issue:`39338`)
2223
-

pandas/_libs/tslibs/nattype.pyx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ cdef class _NaT(datetime):
127127
result.fill(_nat_scalar_rules[op])
128128
elif other.dtype.kind == "O":
129129
result = np.array([PyObject_RichCompare(self, x, op) for x in other])
130+
elif op == Py_EQ:
131+
result = np.zeros(other.shape, dtype=bool)
132+
elif op == Py_NE:
133+
result = np.ones(other.shape, dtype=bool)
130134
else:
131135
return NotImplemented
132136
return result

pandas/plotting/_matplotlib/compat.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ def inner():
2222
mpl_ge_3_1_0 = _mpl_version("3.1.0", operator.ge)
2323
mpl_ge_3_2_0 = _mpl_version("3.2.0", operator.ge)
2424
mpl_ge_3_3_0 = _mpl_version("3.3.0", operator.ge)
25+
mpl_ge_3_4_0 = _mpl_version("3.4.0", operator.ge)

pandas/plotting/_matplotlib/tools.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,11 @@ def handle_shared_axes(
392392
row_num = lambda x: x.rowNum
393393
col_num = lambda x: x.colNum
394394

395+
if compat.mpl_ge_3_4_0():
396+
is_first_col = lambda x: x.get_subplotspec().is_first_col()
397+
else:
398+
is_first_col = lambda x: x.is_first_col()
399+
395400
if nrows > 1:
396401
try:
397402
# first find out the ax layout,
@@ -423,7 +428,7 @@ def handle_shared_axes(
423428
# only the first column should get y labels -> set all other to
424429
# off as we only have labels in the first column and we always
425430
# have a subplot there, we can skip the layout test
426-
if ax.is_first_col():
431+
if is_first_col(ax):
427432
continue
428433
if sharey or _has_externally_shared_axis(ax, "y"):
429434
_remove_labels_from_axis(ax.yaxis)

pandas/tests/plotting/frame/test_frame.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,9 @@ def test_plot_scatter_with_categorical_data(self, x, y):
746746

747747
_check_plot_works(df.plot.scatter, x=x, y=y)
748748

749-
def test_plot_scatter_with_c(self):
749+
def test_plot_scatter_with_c(self, request):
750+
from pandas.plotting._matplotlib.compat import mpl_ge_3_4_0
751+
750752
df = DataFrame(
751753
np.random.randn(6, 4),
752754
index=list(string.ascii_letters[:6]),
@@ -758,9 +760,10 @@ def test_plot_scatter_with_c(self):
758760
# default to Greys
759761
assert ax.collections[0].cmap.name == "Greys"
760762

761-
# n.b. there appears to be no public method
762-
# to get the colorbar label
763-
assert ax.collections[0].colorbar._label == "z"
763+
if mpl_ge_3_4_0():
764+
assert ax.collections[0].colorbar.ax.get_ylabel() == "z"
765+
else:
766+
assert ax.collections[0].colorbar._label == "z"
764767

765768
cm = "cubehelix"
766769
ax = df.plot.scatter(x="x", y="y", c="z", colormap=cm)

pandas/tests/scalar/test_nat.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,47 @@ def test_nat_comparisons_invalid(other_and_type, symbol_and_op):
590590
op(other, NaT)
591591

592592

593+
@pytest.mark.parametrize(
594+
"other",
595+
[
596+
np.array(["foo"] * 2, dtype=object),
597+
np.array([2, 3], dtype="int64"),
598+
np.array([2.0, 3.5], dtype="float64"),
599+
],
600+
ids=["str", "int", "float"],
601+
)
602+
def test_nat_comparisons_invalid_ndarray(other):
603+
# GH#40722
604+
expected = np.array([False, False])
605+
result = NaT == other
606+
tm.assert_numpy_array_equal(result, expected)
607+
result = other == NaT
608+
tm.assert_numpy_array_equal(result, expected)
609+
610+
expected = np.array([True, True])
611+
result = NaT != other
612+
tm.assert_numpy_array_equal(result, expected)
613+
result = other != NaT
614+
tm.assert_numpy_array_equal(result, expected)
615+
616+
for symbol, op in [
617+
("<=", operator.le),
618+
("<", operator.lt),
619+
(">=", operator.ge),
620+
(">", operator.gt),
621+
]:
622+
msg = f"'{symbol}' not supported between"
623+
624+
with pytest.raises(TypeError, match=msg):
625+
op(NaT, other)
626+
627+
if other.dtype == np.dtype("object"):
628+
# uses the reverse operator, so symbol changes
629+
msg = None
630+
with pytest.raises(TypeError, match=msg):
631+
op(other, NaT)
632+
633+
593634
def test_compare_date():
594635
# GH#39151 comparing NaT with date object is deprecated
595636
# See also: tests.scalar.timestamps.test_comparisons::test_compare_date

0 commit comments

Comments
 (0)