From 5e926819df59611326ec004bce572463e1809ef7 Mon Sep 17 00:00:00 2001 From: AKHIL-149 Date: Wed, 10 Dec 2025 21:09:33 -0600 Subject: [PATCH 1/3] fix pivot_table duplicates on py3.14 with old numpy found the real issue - searchsorted is broken with python 3.14 + numpy 1.26. it's not compress_group_index, it's the compressor calculation in unstack that uses searchsorted. just fallback to the unique/return_index approach for this combo, same as what the non-sorted path does. works with 100k rows now. --- pandas/core/reshape/reshape.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pandas/core/reshape/reshape.py b/pandas/core/reshape/reshape.py index accb577d5345c..a936a6b9130e1 100644 --- a/pandas/core/reshape/reshape.py +++ b/pandas/core/reshape/reshape.py @@ -234,7 +234,16 @@ def _make_selectors(self) -> None: self.group_index = comp_index self.mask = mask if self.sort: - self.compressor = comp_index.searchsorted(np.arange(ngroups)) + import sys + # GH 63314: avoid searchsorted bug with py3.14 + numpy < 2.0 + numpy_major = int(np.__version__.split('.')[0]) + has_searchsorted_bug = sys.version_info >= (3, 14) and numpy_major < 2 + + if has_searchsorted_bug: + # use manual approach instead of buggy searchsorted + self.compressor = np.sort(np.unique(comp_index, return_index=True)[1]) + else: + self.compressor = comp_index.searchsorted(np.arange(ngroups)) else: self.compressor = np.sort(np.unique(comp_index, return_index=True)[1]) From 246ffec81a446873924c03d34b44517f2002cf48 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 03:44:23 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pandas/core/reshape/reshape.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/reshape/reshape.py b/pandas/core/reshape/reshape.py index a936a6b9130e1..1842e50c9ba7f 100644 --- a/pandas/core/reshape/reshape.py +++ b/pandas/core/reshape/reshape.py @@ -235,8 +235,9 @@ def _make_selectors(self) -> None: self.mask = mask if self.sort: import sys + # GH 63314: avoid searchsorted bug with py3.14 + numpy < 2.0 - numpy_major = int(np.__version__.split('.')[0]) + numpy_major = int(np.__version__.split(".")[0]) has_searchsorted_bug = sys.version_info >= (3, 14) and numpy_major < 2 if has_searchsorted_bug: From af06a7797db6c577fcd6d57c10ad41b99f1950c9 Mon Sep 17 00:00:00 2001 From: AKHIL-149 Date: Fri, 12 Dec 2025 13:18:24 -0600 Subject: [PATCH 3/3] use pandas compat constants for version checks addressing review feedback - use PY314 and np_version_gt2 instead of manual version parsing --- pandas/core/reshape/reshape.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pandas/core/reshape/reshape.py b/pandas/core/reshape/reshape.py index 1842e50c9ba7f..4b451f707e4c2 100644 --- a/pandas/core/reshape/reshape.py +++ b/pandas/core/reshape/reshape.py @@ -234,13 +234,11 @@ def _make_selectors(self) -> None: self.group_index = comp_index self.mask = mask if self.sort: - import sys + from pandas.compat import PY314 + from pandas.compat.numpy import np_version_gt2 # GH 63314: avoid searchsorted bug with py3.14 + numpy < 2.0 - numpy_major = int(np.__version__.split(".")[0]) - has_searchsorted_bug = sys.version_info >= (3, 14) and numpy_major < 2 - - if has_searchsorted_bug: + if PY314 and not np_version_gt2: # use manual approach instead of buggy searchsorted self.compressor = np.sort(np.unique(comp_index, return_index=True)[1]) else: