nearest_ranges: honour preserve_input_order for direction="upstream"/"downstream" - #175
Open
youdie006 wants to merge 1 commit into
Open
Conversation
nearest_ranges(direction="upstream"/"downstream") returned rows grouped by strand regardless of preserve_input_order - the option was silently inert on a directional query, while direction="any" honoured it. The directional path splits self by strand (each strand searches the opposite coordinate direction) then recombines with a plain pd.concat(per_strand), which appends every forward row then every reverse row and never restores the interleaving. Carry each row's position in self through the split and stable-sort the concatenated frame back into input order when preserve_input_order is set, mirroring the ruranges sort_output positional-order semantics the "any" branch already uses (and the ordering standardization shared with polaranges in pyranges#165). The index alone can't stand in for position, since k > 1 duplicates it and the caller's index may be non-unique, so a positional order column rides through the split. preserve_input_order=False is unchanged (still grouped). Fixes pyranges#169.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #169.
nearest_ranges(direction="upstream"/"downstream")returns rows grouped by strand regardless ofpreserve_input_order-- the option is silently inert on a directional query.direction="any"is unaffected.Repro (interleaved-strand query)
a, b, c, d0, 1, 2, 3a, c, b, d0, 2, 1, 3<- grouped by stranda, c, b, d0, 2, 1, 3a, c, b, d0, 2, 1, 3a, c, b, d0, 2, 1, 3The two
preserve_input_ordervalues give identical output for the directional cases, and the returned index[0, 2, 1, 3]is not the input index[0, 1, 2, 3], which matters becausePyRangesotherwise preserves the input index.Root cause
The docstring promises
preserve_input_order(defaultTrue) "preserve[s] the original input order in the result", anddirection="any"delivers exactly that -- it callsRangeFrame.nearest_rangesonce, where the flag maps to ruranges'sort_outputand rows come back in self's positional input order.The directional path has to split
selfby strand (each strand searches the opposite coordinate direction), then recombines with a plainpd.concat(per_strand). The flag is forwarded into each half, so order holds within a strand, but the concat appends every forward row then every reverse row and nothing restores the interleaving between them.Fix
Carry each row's position in
selfthrough the split and stable-sort the concatenated frame back into input order whenpreserve_input_orderis set -- mirroring the rurangessort_outputpositional-order semantics thedirection="any"branch already uses, so the ordering rule is now consistent across all directions (and consistent with the ordering standardization shared with polaranges in #165). The index alone can't stand in for the position, sincek > 1duplicates it and the caller's index may be non-unique, so a positional order column rides through the split.preserve_input_order=Falseis unchanged (still grouped, faster). This is user-visible for directional queries and may deserve its own release note.Tests
Adds a regression test on the interleaved-strand frame from the issue: directional queries with
preserve_input_order=Truenow matchdirection="any"(input order + original index),direction="any"stays correct, andpreserve_input_order=Falsestays grouped. RED on current master (a, c, b, d/[0, 2, 1, 3]), GREEN after the fix. Onedirection='downstream'doctest updated to the corrected input order.Reported and diagnosed by @marco-mariotti.
This change was prepared with AI assistance (Claude).