diff --git a/CHANGELOG.md b/CHANGELOG.md index dc62e52..b3e6b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,13 @@ # Changelog -## Version 0.8.0 - 0.8.4 +## Version 0.8.0 - 0.8.5 - Rename `GenomicRangesList` to `CompressedGenomicRangesList` and now extends compressed-lists. - Classes extend `BiocObject` from biocutils, provides a default metadata attribute and helper functions. - Rename `validate` to `_validate` for consistency with the rest of the packages and classes. - Fix for empty compressed genomic ranges list. - Aliases `GRanges` and `CompressedGRangesList`. +- Fixed a bug in `to_pandas()` when `names` and `mcols` are present. ## Version 0.7.0 - 0.7.3 diff --git a/src/genomicranges/GenomicRanges.py b/src/genomicranges/GenomicRanges.py index 17a1373..acb1ae6 100644 --- a/src/genomicranges/GenomicRanges.py +++ b/src/genomicranges/GenomicRanges.py @@ -1006,13 +1006,13 @@ def to_pandas(self): _rdf["seqnames"] = self.get_seqnames() _rdf["strand"] = self.get_strand(as_type="list") - if self._names is not None: - _rdf.index = self._names - if self._mcols is not None: if self._mcols.shape[1] > 0: _rdf = pd.concat([_rdf, self._mcols.to_pandas()], axis=1) + if self._names is not None: + _rdf.index = list(self._names) + return _rdf @classmethod @@ -1085,10 +1085,12 @@ def to_polars(self): import polars as pl _rdf = self._ranges.to_polars() - _rdf = _rdf.with_columns(seqnames=self.get_seqnames(), strand=self.get_strand(as_type="list")) + _rdf = _rdf.with_columns( + seqnames=pl.Series(self.get_seqnames()), strand=pl.Series(self.get_strand(as_type="list")) + ) if self._names is not None: - _rdf = _rdf.with_columns(rownames=self._names) + _rdf = _rdf.with_columns(rownames=pl.Series(list(self._names))) if self._mcols is not None: if self._mcols.shape[1] > 0: diff --git a/tests/test_gr_basic.py b/tests/test_gr_basic.py index 1e905e8..57f2ef6 100644 --- a/tests/test_gr_basic.py +++ b/tests/test_gr_basic.py @@ -113,6 +113,44 @@ def test_export_pandas_with_mcols(): assert isinstance(df, pd.DataFrame) +def test_export_pandas_with_names_and_mcols(): + from biocframe import BiocFrame + from iranges import IRanges + + ranges = IRanges(start=[0, 10, 20], width=[5, 5, 5]) + mcols = BiocFrame({"gene_id": ["g1", "g2", "g3"], "gene_name": ["A", "B", "C"]}) + gr_named = GenomicRanges( + seqnames=["1", "1", "1"], + ranges=ranges, + strand=["+", "+", "-"], + names=["g1", "g2", "g3"], + mcols=mcols, + ) + df = gr_named.to_pandas() + assert df is not None + assert df.shape == (3, 7) + assert df.index.tolist() == ["g1", "g2", "g3"] + + +def test_export_polars_with_names_and_mcols(): + from biocframe import BiocFrame + from iranges import IRanges + + ranges = IRanges(start=[0, 10, 20], width=[5, 5, 5]) + mcols = BiocFrame({"gene_id": ["g1", "g2", "g3"], "gene_name": ["A", "B", "C"]}) + gr_named = GenomicRanges( + seqnames=["1", "1", "1"], + ranges=ranges, + strand=["+", "+", "-"], + names=["g1", "g2", "g3"], + mcols=mcols, + ) + df = gr_named.to_polars() + assert df is not None + assert df.shape == (3, 8) # 8 because polars adds a 'rownames' column + assert df["rownames"].to_list() == ["g1", "g2", "g3"] + + def test_combine(): g_src = GenomicRanges( seqnames=["chr1", "chr2", "chr1", "chr3", "chr2"],