BUG/PERF: Series.combine passes Series on duplicate index labels - #67446
BUG/PERF: Series.combine passes Series on duplicate index labels#67446rhshadrach wants to merge 6 commits into
Conversation
jbrockmendel
left a comment
There was a problem hiding this comment.
Does this change any of these cases and are the changes intentional?
left = pd.Series([1, 2], index=pd.date_range("2020", periods=2))
right = pd.Series([10, 20], index=pd.date_range("2020", periods=2, tz="UTC"))
left.combine(right, lambda x, y: x + y, fill_value=0)
mi1 = pd.MultiIndex.from_tuples([("a", 1), ("b", 2)], names=["x", "y"])
mi2 = pd.MultiIndex.from_tuples([("a", 1), ("c", 3)], names=["p", "q"])
left = pd.Series([1, 2], index=mi1)
right = pd.Series([10, 20], index=mi2)
left.combine(right, lambda x, y: x + y, fill_value=0)
left = pd.Series([1, 2], index=mi1)
right = pd.Series([10, 20], index=["a", "b"])
left.combine(right, lambda x, y: x + y)
|
Thanks @jbrockmendel. If I'm missing something and we feel the duplicate case is ambiguous, we could instead raise. That could technically be breaking behavior. No one has complained about duplicate behavior on the issue tracker at all and I'm wondering if that's due in part to this method not seeing much use. But there could be someone out there using today's dups behavior as-is. While implementing duplicate-handling behavior is 100% defensible as a bugfix here, raising a ValueError is still defensible but I think less so. Benchmarks in OP have been updated. |
| tm.assert_numpy_array_equal(result, expected) | ||
|
|
||
|
|
||
| def test_pairwise_indexer(): |
| - Bug in :meth:`DataFrame.stack` raising a bare ``AssertionError`` or an ``IndexError`` when ``level`` contained duplicate entries, including duplicates produced by resolving level names or negative level numbers; it now raises an informative ``ValueError`` (:issue:`66588`) | ||
| - Bug in :meth:`DataFrame.unstack` and :meth:`Series.unstack` with ``sort=False`` placing values under the wrong row labels, or collapsing distinct index combinations into a single row (:issue:`62816`) | ||
| - Bug in :meth:`Index.union` where the result could be unsorted when both inputs were monotonic increasing but disjoint, when ``sort`` was not ``False`` (:issue:`54646`) | ||
| - Fixed bug in :meth:`Series.sort_values` where ``ignore_index=True`` had no effect on an already-sorted Series (:issue:`65833`) |
There was a problem hiding this comment.
was this deleted on purpose?
| left = Series([1, 2, 3], index=["a", "a", "b"]) | ||
| right = Series([10, 20], index=["a", "b"]) | ||
| result = left.combine(right, lambda x, y: x + y, fill_value=0) | ||
| expected = Series([11, 2, 23], index=["a", "a", "b"]) |
There was a problem hiding this comment.
is it obvious that this should be [11, 2, 23] and not [11, 12, 23]?
There was a problem hiding this comment.
This is the join-vs-union behavior I alluded to in #67446 (comment). From what I can tell, the history has always intended it to be a union here, and combine certainly doesn't follow pandas join-semantics in any cases. That makes it obvious to me it should be [11, 2, 23], but I can't say I feel 100% confident that maybe some of this wasn't purposefully decided.
Assuming we're still good with union-behavior, I'll add a comment here.
There was a problem hiding this comment.
ok, thanks for taking a look
Generated by Claude Fable 5. Reviewed and refined by me.
When Series.combine gets an index with duplicate labels, it starts passing Series to the UDF.
The docstring for
funcstates:By moving to this implementation, we also have significant perf improvements.