Skip to content

Commit

Permalink
fix(api): ensure the order of duplicate non-renamed columns in `reloc…
Browse files Browse the repository at this point in the history
…ate` is preserved
  • Loading branch information
cpcloud authored and gforsyth committed Sep 27, 2023
1 parent 86b4c6f commit 19a59aa
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
37 changes: 33 additions & 4 deletions ibis/expr/types/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3898,6 +3898,33 @@ def relocate(
├───────┼───────┼────────┼────────┤
│ 1 │ 1 │ a │ a │
└───────┴───────┴────────┴────────┘
When there are duplicate **renames** in a call to relocate, the
last one is preserved
>>> t.relocate(e="d", f="d")
┏━━━━━━━━┳━━━━━━━┳━━━━━━━━┳━━━━━━━┓
┃ f ┃ a ┃ b ┃ c ┃
┡━━━━━━━━╇━━━━━━━╇━━━━━━━━╇━━━━━━━┩
│ string │ int64 │ string │ int64 │
├────────┼───────┼────────┼───────┤
│ a │ 1 │ a │ 1 │
└────────┴───────┴────────┴───────┘
However, if there are duplicates that are **not** part of a rename, the
order specified in the relocate call is preserved
>>> t.relocate(
... "b",
... s.of_type("string"), # "b" is a string column, so the selector matches
... )
┏━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┓
┃ b ┃ d ┃ a ┃ c ┃
┡━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━┩
│ string │ string │ int64 │ int64 │
├────────┼────────┼───────┼───────┤
│ a │ a │ 1 │ 1 │
└────────┴────────┴───────┴───────┘
"""
import ibis.selectors as s

Expand All @@ -3917,11 +3944,13 @@ def relocate(
zip(kwargs.keys(), map(s._to_selector, kwargs.values())),
):
for pos in sel.positions(self):
if pos in sels:
# make sure the last duplicate column wins by reinserting
# the position if it already exists
renamed = name is not None
if pos in sels and renamed:
# **only when renaming**: make sure the last duplicate
# column wins by reinserting the position if it already
# exists
del sels[pos]
sels[pos] = name if name is not None else table_columns[pos]
sels[pos] = name if renamed else table_columns[pos]

ncols = len(table_columns)

Expand Down
6 changes: 6 additions & 0 deletions ibis/tests/expr/test_relocate.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ def test_move_blocks():
assert t.relocate(s.of_type("string"), after=s.numeric()).columns == list("xyab")


def test_duplicates_not_renamed():
t = ibis.table(dict(x="int", y="int"))
assert t.relocate("y", s.numeric()).columns == list("yx")
assert t.relocate("y", s.numeric(), "y").columns == list("yx")


def test_keep_non_contiguous_variables():
t = ibis.table(dict.fromkeys("abcde", "int"))
assert t.relocate("b", after=s.c("a", "c", "e")).columns == list("acdeb")
Expand Down

0 comments on commit 19a59aa

Please sign in to comment.