Skip to content
Closed
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
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## [Upcoming release](https://github.com/open2c/bioframe/compare/v0.8.0...HEAD)

Bug fixes:

- `assign_view(..., drop_unassigned=True)` now drops only intervals that fall outside the view,
instead of also dropping rows that contain NaNs in unrelated columns.

## v0.8.0

Date: 2025-04-08
Expand Down
4 changes: 3 additions & 1 deletion src/bioframe/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -1893,7 +1893,9 @@ def assign_view(
out_df.rename(columns={view_name_col + "_view": df_view_col}, inplace=True)

if drop_unassigned:
out_df = out_df.iloc[pd.isna(out_df).any(axis=1).values == 0, :]
# only drop intervals that weren't assigned to a view region, not rows
# that happen to contain NaNs in other columns
out_df = out_df[pd.notna(out_df[df_view_col]).values]
out_df.reset_index(inplace=True, drop=True)

return_cols = [*list(df.columns), df_view_col]
Expand Down
21 changes: 21 additions & 0 deletions tests/test_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -2289,3 +2289,24 @@ def test_sort_bedframe():
assert (
df.dtypes == bioframe.sort_bedframe(df, view_df, view_name_col="fruit").dtypes
).all()


def test_assign_view_drop_unassigned_keeps_nan_in_other_columns():
# drop_unassigned should only drop intervals that fall outside the view, not
# intervals that merely contain NaNs in unrelated columns (e.g. cooler bins with
# missing weights). See open2c/bioframe#160.
view_df = bioframe.make_viewframe([("chr1", 0, 100, "region1")])
df = pd.DataFrame(
{
"chrom": ["chr1", "chr1", "chr2"],
"start": [10, 30, 10],
"end": [20, 40, 20],
"value": [np.nan, 5.0, 7.0],
}
)
result = bioframe.assign_view(df, view_df, drop_unassigned=True)

# chr2:10-20 is outside the view and dropped; chr1:10-20 is assigned and kept
# even though its `value` is NaN.
assert list(zip(result["chrom"], result["start"])) == [("chr1", 10), ("chr1", 30)]
assert pd.isna(result.loc[0, "value"])