Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion dascore/utils/pd.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,9 @@ def _check_misdirected_range_query(key, val, df):
base = key[:-4] if key.endswith(("_min", "_max")) else None
if base is None or not {f"{base}_min", f"{base}_max"}.issubset(set(df.columns)):
return
if not any(x is ... or x is None for x in val):
# Only a two element sequence can be a range. Anything else is a
# membership check, where None may be a legitimate value to match.
if len(val) != 2 or not any(x is ... or x is None for x in val):
return
msg = (
f"An open bound (... or None) is not valid in the query for column "
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorial/coords.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ sorted_data = data[indexer, :]

### Snap

[`snap`](`dascore.core.coords.BaseCoord.snap`) replaces coordinate values with an evenly sampled range spanning the same minimum and maximum. This intentionally loses interior precision and should be used only when that idealization is acceptable. For a full patch, [`Patch.snap_coords(...)`](`dascore.Patch.snap_coords`) also sorts the selected dimensions and applies the same indexing to the data.
[`snap`](`dascore.core.coords.BaseCoord.snap`) replaces coordinate values with an evenly sampled range spanning the same minimum and maximum. This intentionally loses interior precision and should be used only when that idealization is acceptable. Unlike [`sort`](`dascore.core.coords.BaseCoord.sort`), it returns only a new coordinate and no indexer, because it replaces the values rather than permuting them, so for an unsorted coordinate the snapped values no longer label the samples they used to. When data alignment matters, use [`CoordManager.snap`](`dascore.core.coordmanager.CoordManager.snap`), which sorts the coordinate and its associated array together before snapping, or [`Patch.snap_coords(...)`](`dascore.Patch.snap_coords`), which does the same across the selected dimensions of a patch.

```{python}
import numpy as np
Expand Down
9 changes: 9 additions & 0 deletions tests/test_utils/test_pd.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,15 @@ def test_closed_range_on_interval_column_still_isin(self, example_df_2):
out = filter_df(example_df_2, bp_min=tuple(vals))
assert np.all(out == example_df_2["bp_min"].isin(vals))

@pytest.mark.parametrize("val", [[None], [100, None, 125]])
def test_non_range_shaped_collection_still_isin(self, example_df_2, val):
"""
Only a two element sequence can be a range, so other collections stay
membership checks even when they contain None.
"""
out = filter_df(example_df_2, bp_min=val)
assert np.all(out == example_df_2["bp_min"].isin(val))

def test_ellipsis_kept_for_non_interval_column(self, example_df_2):
"""
Columns with no min/max pair are plain isin checks; an ellipsis there
Expand Down
Loading