Skip to content

Commit

Permalink
add method get_column. Set deprecation warning for column(). (#61)
Browse files Browse the repository at this point in the history
Rename column to `get_column` and row to `get_row`. Update docstrings and readme.
  • Loading branch information
jkanche authored Nov 1, 2023
1 parent 6028c04 commit ab5426e
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 24 deletions.
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Properties can be accessed directly from the object, for e.g. column names, row

```python
# Dimensionality or shape
print(bframe.dims)
print(bframe.shape)

## output
## (3, 2)
Expand Down Expand Up @@ -133,6 +133,37 @@ print(bframe)
[1] ENS00002 BIN1 3
[2] ENS00003 ESR1 4

##### Functional style

Properties can also be accessed or set using a functional approach

To get column names,

```python
print(bframe.get_column_names())

## output
## ['ensembl', 'symbol']
```

To set new column names,

```python
# set new column names
bframe.set_column_names(names = ["column1", "column2"], in_place=True)
print(bframe)
```

## output
BiocFrame with 3 rows and 2 columns
column1 column2
<list> <list>
[0] ENS00001 MAP1A
[1] ENS00002 BIN1
[2] ENS00003 ESR1

If **in_place** is `True`, we mutate the object, otherwise returns a new instance.

### Subset `BiocFrame`

Use the subset (`[]`) operator to **slice** the object,
Expand Down
99 changes: 76 additions & 23 deletions src/biocframe/BiocFrame.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
from collections import OrderedDict
from typing import Any, Dict, List, Optional, Tuple, Union, Sequence
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
from warnings import warn

import biocutils as ut
from biocgenerics import show_as_cell
from biocgenerics.colnames import colnames as colnames_generic
from biocgenerics.colnames import set_colnames
from biocgenerics.combine import combine
from biocgenerics.combine_cols import combine_cols
from biocgenerics.combine_rows import combine_rows
from biocgenerics.rownames import rownames as rownames_generic
from biocgenerics.rownames import set_rownames
from biocgenerics import show_as_cell
from biocutils import is_list_of_type, normalize_subscript
import biocutils as ut

from ._validators import validate_cols, validate_rows, validate_unique_list
from .Factor import Factor
Expand Down Expand Up @@ -363,7 +362,7 @@ def row_names(self, names: Optional[List]):
"""

warn(
"Setting property 'row_names'is an in-place operation, use 'set_row_names' instead",
"Setting property 'row_names' is an in-place operation, use 'set_row_names' instead",
UserWarning,
)

Expand Down Expand Up @@ -444,7 +443,7 @@ def column_names(self, names: List[str]):
"""

warn(
"Setting property 'column_names'is an in-place operation, use 'set_column_names' instead",
"Setting property 'column_names' is an in-place operation, use 'set_column_names' instead",
UserWarning,
)

Expand Down Expand Up @@ -490,7 +489,7 @@ def mcols(self, mcols: Union[None, "BiocFrame"]):
mcols (Union[None, BiocFrame]): New metadata about column to set.
"""
warn(
"Setting property 'mcols'is an in-place operation, use 'set_mcols' instead",
"Setting property 'mcols' is an in-place operation, use 'set_mcols' instead",
UserWarning,
)

Expand Down Expand Up @@ -541,7 +540,7 @@ def metadata(self, metadata: dict):
metadata (dict): New metadata object.
"""
warn(
"Setting property 'metadata'is an in-place operation, use 'set_metadata' instead",
"Setting property 'metadata' is an in-place operation, use 'set_metadata' instead",
UserWarning,
)

Expand All @@ -558,7 +557,7 @@ def has_column(self, name: str) -> bool:
"""
return name in self.column_names

def column(self, index_or_name: Union[str, int]) -> Any:
def get_column(self, index_or_name: Union[str, int]) -> Any:
"""Access a column by index or column label.
Args:
Expand All @@ -585,8 +584,35 @@ def column(self, index_or_name: Union[str, int]) -> Any:

return self[None, index_or_name]

def row(self, index_or_name: Union[str, int]) -> dict:
"""Access a row by index or row name.
def column(self, index_or_name: Union[str, int]) -> Any:
"""Access a column by index or column label. Alias to :py:meth:`~biocframe.BiocFrame.BiocFrame.get_column`.
Args:
index_or_name (Union[str, int]): Name of the column, which must a valid name in
:py:attr:`~biocframe.BiocFrame.BiocFrame.column_names`.
Alternatively, you may provide the integer index of the column to access.
Raises:
ValueError:
If ``index_or_name`` is not in column names.
If the integer index is greater than the number of columns.
TypeError:
If ``index_or_name`` is neither a string nor an integer.
Returns:
Any: Column with its original type preserved.
"""

warn(
"Method 'column' is deprecated, use 'get_column' instead",
DeprecationWarning,
)

return self.get_column(index_or_name)

def get_row(self, index_or_name: Union[str, int]) -> dict:
"""Access a row by index or row name.Alias to :py:meth:`~biocframe.BiocFrame.BiocFrame.get_row`.
Args:
index_or_name (Union[str, int]): Integer index of the row to access.
Expand All @@ -612,6 +638,33 @@ def row(self, index_or_name: Union[str, int]) -> dict:

return self[index_or_name, None]

def row(self, index_or_name: Union[str, int]) -> dict:
"""Access a row by index or row name.
Args:
index_or_name (Union[str, int]): Integer index of the row to access.
Alternatively, you may provide a string specifying the row to access,
only if :py:attr:`~biocframe.BiocFrame.BiocFrame.row_names` are available.
Raises:
ValueError:
If ``index_or_name`` is not in row names.
If the integer index is greater than the number of rows.
TypeError:
If ``index_or_name`` is neither a string nor an integer.
Returns:
dict: A dictionary with keys as column names and their values.
"""

warn(
"Method 'row' is deprecated, use 'get_row' instead",
DeprecationWarning,
)

return self.get_row(index_or_name)

def slice(
self,
row_indices_or_names: Optional[SlicerTypes] = None,
Expand Down Expand Up @@ -644,7 +697,7 @@ def slice(

# slice the columns and data
if column_indices_or_names is not None:
new_column_indices, is_col_scalar = normalize_subscript(
new_column_indices, is_col_scalar = ut.normalize_subscript(
column_indices_or_names, len(new_column_names), new_column_names
)

Expand All @@ -657,7 +710,7 @@ def slice(
new_number_of_rows = None
if row_indices_or_names is not None:
new_row_names = self.row_names
new_row_indices, is_row_scalar = normalize_subscript(
new_row_indices, is_row_scalar = ut.normalize_subscript(
row_indices_or_names, self.shape[0], new_row_names
)

Expand Down Expand Up @@ -785,9 +838,9 @@ def __getitem__(

if isinstance(args, list):
# column names if everything is a string
if is_list_of_type(args, str):
if ut.is_list_of_type(args, str):
return self.slice(None, args)
elif is_list_of_type(args, int):
elif ut.is_list_of_type(args, int):
return self.slice(args, None)
else:
raise TypeError(
Expand Down Expand Up @@ -850,13 +903,13 @@ def __setitem__(self, args, value: Union[List, "BiocFrame"]):
if isinstance(args, tuple):
rows, cols = args

row_idx, scalar = normalize_subscript(
row_idx, scalar = ut.normalize_subscript(
rows, self.shape[0], names=self._row_names
)
if scalar:
raise TypeError("row indices should be a sequence or slice")

col_idx, scalar = normalize_subscript(
col_idx, scalar = ut.normalize_subscript(
cols, self.shape[1], names=self._column_names
)
if scalar:
Expand Down Expand Up @@ -942,13 +995,13 @@ def set_column(
if isinstance(args, tuple):
rows, cols = args

row_idx, scalar = normalize_subscript(
row_idx, scalar = ut.normalize_subscript(
rows, output.shape[0], names=output._row_names
)
if scalar:
raise TypeError("row indices should be a sequence or slice")

col_idx, scalar = normalize_subscript(
col_idx, scalar = ut.normalize_subscript(
cols, output.shape[1], names=output._column_names
)
if scalar:
Expand Down Expand Up @@ -1157,7 +1210,7 @@ def combine(self, *other):
Returns:
The same type as caller with the combined data.
"""
if not is_list_of_type(other, BiocFrame):
if not ut.is_list_of_type(other, BiocFrame):
raise TypeError("All objects to combine must be BiocFrame objects.")

all_objects = [self] + list(other)
Expand Down Expand Up @@ -1284,22 +1337,22 @@ def copy(self):

@combine.register(BiocFrame)
def _combine_bframes(*x: BiocFrame):
if not is_list_of_type(x, BiocFrame):
if not ut.is_list_of_type(x, BiocFrame):
raise ValueError("All elements to `combine` must be `BiocFrame` objects.")
return x[0].combine(*x[1:])


@combine_rows.register(BiocFrame)
def _combine_rows_bframes(*x: BiocFrame):
if not is_list_of_type(x, BiocFrame):
if not ut.is_list_of_type(x, BiocFrame):
raise ValueError("All elements to `combine_rows` must be `BiocFrame` objects.")

return x[0].combine(*x[1:])


@combine_cols.register(BiocFrame)
def _combine_cols_bframes(*x: BiocFrame):
if not is_list_of_type(x, BiocFrame):
if not ut.is_list_of_type(x, BiocFrame):
raise ValueError("All elements to `combine_cols` must be `BiocFrame` objects.")

raise NotImplementedError(
Expand Down

0 comments on commit ab5426e

Please sign in to comment.