mutcleaner.cleaners.basic_cleaners#
Functions
|
Add multiple constant-valued columns to a DataFrame using a dictionary. |
|
Add full wild-type sequences to the dataset from sequence dictionary |
|
Resolve/aggregate label columns for rows sharing the same (composite) name. |
|
Apply mutations to sequences to generate mutated sequences. |
|
Average label columns for rows sharing the same name. |
|
Convert data types for specified columns. |
|
Convert a mutation DataFrame to the format required by MutationDataset.from_dataframe(). |
|
Extract useful columns and rename them to standard format. |
|
Filter and clean data based on specified conditions. |
|
Infer mutations by comparing wild-type sequences with mutated sequences. |
|
Infer wild-type sequences from mutated sequences and add WT rows. |
|
Merge multiple columns into a single column using a separator |
|
Read dataset from specified file format and return as a pandas DataFrame. |
|
Remap mutation positions using name-specific offsets or position maps. |
|
Replace or remove a literal substring in a specified DataFrame column. |
|
Split a single column into multiple columns using a separator |
|
For each group defined by |
|
Validate and format mutation information. |
- mutcleaner.cleaners.basic_cleaners.add_columns(dataset, columns_to_add, overwrite=True)[source]#
Add multiple constant-valued columns to a DataFrame using a dictionary.
- Parameters:
dataset (
DataFrame) – The input DataFrame to which the ‘dataset_name’ will be added.columns_to_add (
Dict[str,Any]) – A dictionary where keys are the new column names and values are the constant values to assign to all rows in those columns.overwrite (
bool) – Whether to overwrite existing columns with the same name. If False, a warning will be printed and existing columns will be skipped.
- Return type:
DataFrame- Returns:
The DataFrame with the additional columns.
Examples
>>> import pandas as pd >>> df = pd.DataFrame({ ... 'mut_info' : ['A0G', 'V1D', 'K2A'], ... 'mut_seq' : ['GVKDF', 'ADKDF', 'AVADF']}) >>> new_cols = { ... "name": "protein1", ... "wt_seq": "AGKDF" ... } >>> df = add_columns(df, columns_to_add=new_cols) >>> print(list(df.columns)) ['mut_info', 'mut_seq', 'name', 'wt_seq']
- mutcleaner.cleaners.basic_cleaners.add_sequences_to_dataset(dataset, sequence_source, name_column='name', sequence_column='sequence', header_parser=None)[source]#
Add full wild-type sequences to the dataset from sequence dictionary
This function maps sequences from a dictionary to the dataset. Records without matching sequences are separated into the failed dataset.
- Parameters:
dataset (
DataFrame) – Dataset containing protein namessequence_source (
Union[Dict[str,str],str,Path]) – Mapping from protein name to full wild-type sequencename_column (
str) – Column name containing protein identifiers
- Return type:
Tuple[DataFrame,DataFrame]- Returns:
(successful_dataset, failed_dataset) - datasets with and without sequences
Examples
>>> import pandas as pd >>> df = pd.DataFrame({ ... 'name': ['prot1', 'prot2', 'prot3'], ... 'score': [1.0, 2.0, 3.0] ... }) >>> from typing import Dict >>> from mutcleaner.cleaners.basic_cleaners import add_sequences_to_dataset >>> from mutcleaner.loaders import load_sequences
>>> seq_dict = {'prot1': 'AKCD', 'prot2': 'EFGH'} >>> successful, failed = add_sequences_to_dataset(df, seq_dict) >>> print(len(successful)) # Should be 2 2 >>> print(len(failed)) # Should be 1 1
- mutcleaner.cleaners.basic_cleaners.aggregate_labels_by_name(dataset, name_columns, label_columns, remove_origin_columns=True, strategy='mean', *, nearest_by=None, nearest_weights=None, output_suffix=None)[source]#
Resolve/aggregate label columns for rows sharing the same (composite) name. Supports built-in strategies (‘mean’, ‘first’, ‘nearest’) or a custom callable.
- Parameters:
dataset (
DataFrame) – Input dataframe.name_columns (
Union[str,Sequence[str]]) – Column name(s) used for grouping. Supports one or multiple columns.label_columns (
Union[str,Sequence[str]]) – Label column(s) to resolve/aggregate.remove_origin_columns (
bool) – If True, return one row per name with resolved labels using the original label column names. If False, keep original rows and merge resolved values back as extra columns (see output_suffix).strategy (
Union[str,Callable[[DataFrame,List[str]],Series]]) –“mean”: per-group numeric mean for each label (NaNs ignored). - “first”: take the first row in each group for the labels. - “nearest”: pick the row minimizing a multi-criteria distance; requires nearest_by. - Callable(group_df, label_cols) -> pd.Series: custom resolver that returns a single-row Series whose index includes the label columns.
nearest_by (
Union[Sequence[Tuple[str,float]],Dict[str,float],None]) – Criteria for “nearest” strategy. Provide either: * a list of (column, target) pairs in priority order, or * a dict {column: target}. When dict is used, priority order is the insertion order (Python 3.7+ preserves dict insertion order). The distance is computed per criterion as abs(col - target), and rows are compared lexicographically by the (possibly weighted) distance tuple.nearest_weights (
Union[Sequence[Tuple[str,float]],Dict[str,float],None]) – Optional weights for “nearest” strategy (same columns as in nearest_by). If provided, each distance is multiplied by its weight before comparison. Defaults to all weights = 1.0.output_suffix (
Optional[str]) – Suffix used when remove_origin_columns=False to name merged columns. Default depends on strategy: - “_mean_by_name”, “_first_by_name”, “_nearest_by_name”, or “_custom_by_name”.
- Return type:
DataFrame- Returns:
If remove_origin_columns is True: one row per group with resolved labels. Otherwise: original rows + resolved label columns (with suffix).
- Raises:
KeyError – If required columns are missing.
ValueError – If label columns are non-numeric for “mean”, or if “nearest” is selected without nearest_by, or if custom strategy returns invalid shape/index.
Examples
Mean aggregation, one row per name:
>>> import pandas as pd >>> df = pd.DataFrame({ ... "gene": ["A","A","B"], ... "specie": ["hs","hs","hs"], ... "ddG": [1.0, 3.0, 2.0], ... "dTm": [10.0, 30.0, 20.0] ... }) >>> aggregate_labels_by_name( ... df, ... name_columns=["gene","specie"], ... label_columns=["ddG","dTm"], ... strategy="mean", ... remove_origin_columns=True ... ) gene specie ddG dTm 0 A hs 2.0 20.0 1 B hs 2.0 20.0
Nearest row by multiple criteria (temperature, then pH) with weights, keeping original rows and adding resolved columns:
>>> df2 = pd.DataFrame({ ... "gene": ["A","A","A","B"], ... "temperature": [20.0, 24.5, 26.0, 25.0], ... "pH": [7.2, 7.4, 7.3, 7.5], ... "ddG": [1.1, 1.9, 2.2, 2.0], ... "dTm": [9.0, 20.0, 21.0, 20.0], ... }) >>> aggregate_labels_by_name( ... df2, ... name_columns="gene", ... label_columns=["ddG","dTm"], ... strategy="nearest", ... nearest_by=[("temperature", 25.0), ("pH", 7.4)], ... nearest_weights={"temperature": 2.0, "pH": 1.0}, ... remove_origin_columns=False ... ).filter(regex="^gene$|_nearest_by_name$|^ddG$|^dTm$") gene ddG dTm ddG_nearest_by_name dTm_nearest_by_name 0 A 1.1 9.0 1.9 20.0 1 A 1.9 20.0 1.9 20.0 2 A 2.2 21.0 1.9 20.0 3 B 2.0 20.0 2.0 20.0
- mutcleaner.cleaners.basic_cleaners.apply_mutations_to_sequences(dataset, sequence_column='sequence', name_column='name', mutation_column='mut_info', position_columns=None, mutation_sep=',', is_zero_based=True, sequence_type='protein', mutation_type=None, alphabet=None, num_workers=4)[source]#
Apply mutations to sequences to generate mutated sequences.
This function takes mutation information and applies it to wild-type sequences to generate the corresponding mutated sequences. It supports parallel processing and can handle position-based sequence extraction.
- Parameters:
dataset (
DataFrame) – Input dataset containing mutation information and sequence datasequence_column (
str) – Column name containing wild-type sequencesname_column (
str) – Column name containing protein identifiersmutation_column (
str) – Column name containing mutation informationposition_columns (
Optional[Dict[str,str]]) – Position column mapping {“start”: “start_col”, “end”: “end_col”} Used for extracting sequence regionsmutation_sep (
str) – Separator used to split multiple mutations in a single stringis_zero_based (
bool) – Whether origin mutation positions are zero-basedsequence_type (
str) – Type of sequence (‘protein’, ‘dna’, ‘rna’)num_workers (
int) – Number of parallel workers for processing, set to -1 for all available CPUs
- Return type:
Tuple[DataFrame,DataFrame]- Returns:
(successful_dataset, failed_dataset) - datasets with and without errors
Examples
>>> import pandas as pd >>> df = pd.DataFrame({ ... 'name': ['prot1', 'prot1', 'prot2'], ... 'sequence': ['AKCDEF', 'AKCDEF', 'FEGHIS'], ... 'mut_info': ['A0K', 'C2D', 'E1F'], ... 'score': [1.0, 2.0, 3.0] ... }) >>> successful, failed = apply_mutations_to_sequences(df) >>> print(successful['mut_seq'].tolist()) ['KKCDEF', 'AKDDEF', 'FFGHIS'] >>> print(len(failed)) # Should be 0 if all mutations are valid 0
- mutcleaner.cleaners.basic_cleaners.average_labels_by_name(dataset, name_columns, label_columns, remove_origin_columns=True)[source]#
Average label columns for rows sharing the same name.
- Parameters:
df (pd.DataFrame) – Input dataframe.
name_columns (
Union[str,Sequence[str]]) – Column name(s) used for grouping (the “name” keys). Supports a single column or multiple columns for composite keys.label_cols (Union[str, Sequence[str]]) – Label column(s) to average.
remove_origin_columns (
bool) – If True, return one row per name with averaged labels using the ORIGINAL label column names (deduplicated by design). If False, keep original rows and add per-name mean columns named<label>_mean_by_name.
- Return type:
DataFrame- Returns:
If
remove_origin_columnsis True: columns = [name_column] + label_columns (averaged), one row per unique name. - If False: same rows as input plus<label>_mean_by_namecolumns.
- Raises:
KeyError – If
name_columnor any oflabel_columnsis missing.ValueError – If any label column is non-numeric.v
Examples
>>> df = pd.DataFrame({ ... "gene": ["A","A","B"], ... "specie": ["hs","hs","hs"], ... "y1": [1.0, 3.0, 2.0], ... "y2": [10.0, 30.0, 20.0] ... }) >>> # multiple name keys >>> average_labels_by_name(df, ["gene","specie"], ["y1","y2"], remove_origin_columns=True) gene specie y1 y2 0 A hs 2.0 20.0 1 B hs 2.0 20.0
>>> # keep original rows and add means >>> average_labels_by_name(df, "gene", ["y1","y2"], remove_origin_columns=False) gene specie y1 y2 y1_mean_by_name y2_mean_by_name 0 A hs 1.0 10.0 2.0 20.0 1 A hs 3.0 30.0 2.0 20.0 2 B hs 2.0 20.0 2.0 20.0
- mutcleaner.cleaners.basic_cleaners.convert_data_types(dataset, type_conversions, handle_errors='coerce', optimize_memory=True, use_batch_processing=False, chunk_size=10000)[source]#
Convert data types for specified columns.
This function provides unified data type conversion with error handling options. Supports pandas, numpy, and Python built-in types with memory optimization.
- Parameters:
dataset (
DataFrame) – Input dataset with columns to be convertedtype_conversions (
Dict[str,Union[str,Type,dtype]]) – Type conversion mapping in format {column_name: target_type} Supported formats: - String types: ‘float’, ‘int’, ‘str’, ‘category’, ‘bool’, ‘datetime’ - Numpy types: np.float32, np.float64, np.int32, np.int64, etc. - Pandas types: ‘Int64’, ‘Float64’, ‘string’, ‘boolean’ - Python types: float, int, str, boolhandle_errors (
str) – Error handling strategy: ‘raise’, ‘coerce’, or ‘ignore’optimize_memory (
bool) – Whether to automatically optimize memory usage by choosing smaller dtypesuse_batch_processing (
bool) – Whether to use batch processing for large datasetschunk_size (
int) – Chunk size when using batch processing
- Return type:
DataFrame- Returns:
Dataset with converted data types
Examples
>>> import pandas as pd >>> import numpy as np >>> df = pd.DataFrame({ ... 'score': ['1.5', '2.3', '3.7'], ... 'count': ['10', '20', '30'], ... 'name': [123, 456, 789], ... 'flag': ['True', 'False', 'True'] ... }) >>> conversions = { ... 'score': np.float32, ... 'count': 'Int64', ... 'name': 'string', ... 'flag': 'boolean' ... } >>> result = convert_data_types(df, conversions)
- mutcleaner.cleaners.basic_cleaners.convert_to_mutation_dataset_format(df, name_column='name', mutation_column='mut_info', sequence_column=None, mutated_sequence_column='mut_seq', sequence_type='protein', label_column='score', include_wild_type=False, mutation_set_prefix='set', is_zero_based=False, additional_metadata=None)[source]#
Convert a mutation DataFrame to the format required by MutationDataset.from_dataframe().
This function supports two input formats: 1. Format with WT rows: Contains explicit ‘WT’ entries with wild-type sequences 2. Format with sequence column: Each row contains the wild-type sequence
- Parameters:
df – Input DataFrame. Supports two formats:
- Return type:
Tuple[pd.DataFrame, Dict[str, BaseSequence]]
- Returns:
(converted_dataframe, reference_sequences_dict)
converted_dataframe: DataFrame in MutationDataset.from_dataframe() format reference_sequences_dict: Dictionary mapping reference_id to wild-type sequences (extracted from WT rows in Format 1 or sequence column in Format 2)
- Raises:
ValueError – If required columns are missing or mutation strings cannot be parsed.
Examples
>>> import pandas as pd
Format 1: With WT rows and multi-mutations
>>> df1 = pd.DataFrame({ ... 'name': ['prot1', 'prot1', 'prot1', 'prot2', 'prot2'], ... 'mut_info': ['A0S,Q1D', 'C2D', 'WT', 'E0F', 'WT'], ... 'mut_seq': ['SDCDEF', 'AQDDEF', 'AQCDEF', 'FGHIGHK', 'EGHIGHK'], ... 'score': [1.5, 2.0, 0.0, 3.0, 0.0] ... }) >>> result_df1, ref_seqs1 = convert_to_mutation_dataset_format(df1) >>> # Input has 5 rows but output has 6 rows (A0S,Q1D -> 2 rows)
Format 2: With sequence column and multi-mutations
>>> df2 = pd.DataFrame({ ... 'name': ['prot1', 'prot1', 'prot2'], ... 'sequence': ['AKCDEF', 'AKCDEF', 'FEGHIS'], ... 'mut_info': ['A0K,C2D', 'Q1P', 'E1F'], ... 'score': [1.5, 2.0, 3.0], ... 'mut_seq': ['KKDDEF', 'APCDEF', 'FFGHIS'] ... }) >>> result_df2, ref_seqs2 = convert_to_mutation_dataset_format( ... df2, sequence_column='sequence' ... ) >>> print(ref_seqs2['prot1']) AKCDEF >>> # First row generates 2 output rows for A0K and C2D mutations
- mutcleaner.cleaners.basic_cleaners.extract_and_rename_columns(dataset, column_mapping, required_columns=None)[source]#
Extract useful columns and rename them to standard format.
This function extracts specified columns from the input dataset and renames them according to the provided mapping. It helps standardize column names across different datasets.
- Parameters:
dataset (
DataFrame) – Input dataset containing the data to be processedcolumn_mapping (
Dict[str,str]) – Column name mapping from original names to new names Format: {original_column_name: new_column_name}required_columns (
Optional[Sequence[str]]) – Required column names. If None, extracts all mapped columns
- Return type:
DataFrame- Returns:
Dataset with extracted and renamed columns
- Raises:
ValueError – If required columns are missing from the input dataset
Examples
>>> import pandas as pd >>> df = pd.DataFrame({ ... 'uniprot_ID': ['P12345', 'Q67890'], ... 'mutation_type': ['A123B', 'C456D'], ... 'score_value': [1.5, -2.3], ... 'extra_col': ['x', 'y'] ... }) >>> mapping = { ... 'uniprot_ID': 'name', ... 'mutation_type': 'mut_info', ... 'score_value': 'label' ... } >>> result = extract_and_rename_columns(df, mapping) >>> print(result.columns.tolist()) ['name', 'mut_info', 'label']
- mutcleaner.cleaners.basic_cleaners.filter_and_clean_data(dataset, filters=None, exclude_patterns=None, drop_na_columns=None)[source]#
Filter and clean data based on specified conditions.
This function provides flexible data filtering and cleaning capabilities, including value-based filtering, pattern exclusion, and null value removal.
- Parameters:
dataset (
DataFrame) – Input dataset to be filtered and cleanedfilters (
Optional[Dict[str,Union[Any,Callable[[Series],Series]]]]) – Filter conditions in format {column_name: condition_value_or_function} If value is callable, it will be applied to the columnexclude_patterns (
Optional[Dict[str,Union[str,List[str]]]]) – Exclusion patterns in format {column_name: regex_pattern_or_list} Rows matching these patterns will be excludeddrop_na_columns (
Optional[List[str]]) – List of column names where null values should be dropped
- Return type:
Tuple[DataFrame,DataFrame]- Returns:
A tuple containing two datasets:
- successful_datasetpd.DataFrame
Rows that pass all filtering conditions.
- failed_datasetpd.DataFrame
Rows that fail at least one filtering condition.
Examples
>>> import pandas as pd >>> df = pd.DataFrame({ ... 'mut_type': ['A123B', 'wt', 'C456D', 'insert', 'E789F'], ... 'score': [1.5, 2.0, '-', 3.2, 4.1], ... 'quality': ['good', 'bad', 'good', 'good', None] ... }) >>> filters = {'score': lambda x: x != '-'} >>> exclude_patterns = {'mut_type': ['wt', 'insert']} >>> drop_na_columns = ['quality'] >>> successful, failed = filter_and_clean_data(df, filters, exclude_patterns, drop_na_columns) >>> print(len(successful)) # Should be 1 (A123B row) 1
- mutcleaner.cleaners.basic_cleaners.infer_mutations_from_sequences(dataset, wt_sequence_column='wt_seq', mut_sequence_column='mut_seq', mutation_sep=',', sequence_type='protein', num_workers=4)[source]#
Infer mutations by comparing wild-type sequences with mutated sequences.
This function takes wild-type and mutated sequences and identifies the mutations that occurred by comparing them position by position. It only handles sequences of equal length. Uses parallel processing for large datasets.
- Parameters:
dataset (
DataFrame) – Input dataset containing wild-type and mutated sequence data. Each dict should contain the specified column keys.wt_sequence_column (
str) – Column key containing wild-type sequencesmut_sequence_column (
str) – Column key containing mutated sequencesmutation_sep (
str) – Separator used to join multiple mutations in output stringsequence_type (
str) – Type of sequence (‘protein’, ‘dna’, ‘rna’)num_workers (
int) – Number of parallel workers for processing, set to -1 for all available CPUs
- Return type:
Tuple[DataFrame,DataFrame]- Returns:
(successful_results, failed_results) - datasets with and without errors
Examples
>>> dataset = pd.DataFrame([ ... {'name': 'prot1', 'wt_seq': 'AKCDEF', 'mut_seq': 'KKCDEF'}, ... {'name': 'prot1', 'wt_seq': 'AKCDEF', 'mut_seq': 'AKDDEF'}, ... {'name': 'prot2', 'wt_seq': 'FEGHIS', 'mut_seq': 'FFGHIS'}, ... {'name': 'prot3', 'wt_seq': 'ABC', 'mut_seq': 'ASC'} ... ]) >>> successful, failed = infer_mutations_from_sequences(dataset) >>> successful name wt_seq mut_seq inferred_mutations 0 prot1 AKCDEF KKCDEF A0K 1 prot1 AKCDEF AKDDEF C2D 2 prot2 FEGHIS FFGHIS E1F >>> failed name wt_seq mut_seq error_message 3 prot3 ABC ABCD Invalid characters in Protein sequence: {'B'}
- mutcleaner.cleaners.basic_cleaners.infer_wildtype_sequences(dataset, name_column='name', mutation_column='mut_info', sequence_column='mut_seq', label_columns=None, wt_label=0.0, mutation_sep=',', is_zero_based=False, sequence_type='protein', handle_multiple_wt='error', num_workers=4)[source]#
Infer wild-type sequences from mutated sequences and add WT rows.
This function takes mutated sequences and their corresponding mutations to infer the original wild-type sequences. For each protein, it adds WT row(s) to the dataset with the inferred wild-type sequence.
- Parameters:
dataset (
DataFrame) – Input dataset containing mutated sequences and mutation informationname_column (
str) – Column name containing protein identifiersmutation_column (
str) – Column name containing mutation informationsequence_column (
str) – Column name containing mutated sequenceslabel_columns (
Optional[List[str]]) – List of label column names to preservewt_label (
float) – Wild type score for WT rowsmutation_sep (
str) – Separator used to split multiple mutations in a single stringis_zero_based (
bool) – Whether origin mutation positions are zero-basedsequence_type (
Literal['protein','dna','rna']) – Type of sequence (‘protein’, ‘dna’, ‘rna’)handle_multiple_wt (
Literal['error','separate','first']) – How to handle multiple wild-type sequences: ‘separate’, ‘first’, or ‘error’num_workers (
int) – Number of parallel workers for processing, set to -1 for all available CPUs
- Return type:
Tuple[DataFrame,DataFrame]- Returns:
(successful_dataset, problematic_dataset) - datasets with added WT rows
Examples
>>> import pandas as pd >>> df = pd.DataFrame({ ... 'name': ['prot1', 'prot1', 'prot2'], ... 'mut_info': ['A0S', 'C2D', 'E0F'], ... 'mut_seq': ['SQCDEF', 'AQDDEF', 'FGHIGHK'], ... 'score': [1.0, 2.0, 3.0] ... }) >>> success, failed = infer_wildtype_sequences( ... df, label_columns=['score'] ... ) >>> print(len(success)) # Should have original rows + WT rows
- mutcleaner.cleaners.basic_cleaners.merge_columns(dataset, columns_to_merge, new_column_name, separator='_', drop_original=False, na_rep=None, prefix=None, suffix=None, custom_formatter=None)[source]#
Merge multiple columns into a single column using a separator
This function combines values from multiple columns into a new column, with flexible formatting options.
- Parameters:
dataset (
DataFrame) – Input datasetcolumns_to_merge (
List[str]) – List of column names to mergenew_column_name (
str) – Name for the new merged columnseparator (
str) – Separator to use between valuesdrop_original (
bool) – Whether to drop the original columns after mergingna_rep (
Optional[str]) – String representation of NaN values. If None, NaN values are skipped.prefix (
Optional[str]) – Prefix to add to the merged valuesuffix (
Optional[str]) – Suffix to add to the merged valuecustom_formatter (
Optional[Callable[[Series],str]]) – Custom function to format each row. Takes a pd.Series and returns a string. If provided, ignores separator, prefix, suffix parameters.
- Return type:
DataFrame- Returns:
Dataset with the new merged column
Examples
Basic usage:
>>> df = pd.DataFrame({ ... 'gene': ['BRCA1', 'TP53', 'EGFR'], ... 'position': [100, 200, 300], ... 'mutation': ['A', 'T', 'G'] ... }) >>> result = merge_columns(df, ['gene', 'position', 'mutation'], 'mutation_id', separator='_') >>> print(result['mutation_id']) 0 BRCA1_100_A 1 TP53_200_T 2 EGFR_300_G
With prefix and suffix:
>>> result = merge_columns( ... df, ['gene', 'position'], 'gene_pos', ... separator=':', prefix='[', suffix=']' ... ) >>> print(result['gene_pos']) 0 [BRCA1:100] 1 [TP53:200] 2 [EGFR:300]
Handling NaN values:
>>> df_with_nan = pd.DataFrame({ ... 'col1': ['A', 'B', None], ... 'col2': ['X', None, 'Z'], ... 'col3': [1, 2, 3] ... }) >>> result = merge_columns( ... df_with_nan, ['col1', 'col2', 'col3'], 'merged', ... separator='-', na_rep='NA' ... ) >>> print(result['merged']) 0 A-X-1 1 B-NA-2 2 NA-Z-3
Custom formatter:
>>> def format_mutation(row): ... return f"{row['gene']}:{row['position']}{row['mutation']}" >>> result = merge_columns( ... df, ['gene', 'position', 'mutation'], 'hgvs', ... custom_formatter=format_mutation ... ) >>> print(result['hgvs']) 0 BRCA1:100A 1 TP53:200T 2 EGFR:300G
- mutcleaner.cleaners.basic_cleaners.read_dataset(file_path, file_format=None, **kwargs)[source]#
Read dataset from specified file format and return as a pandas DataFrame.
- Parameters:
file_path (
Union[str,Path]) – Path to the dataset filefile_format (
Optional[str]) – Format of the dataset file (“csv”, “tsv”, “xlsx”, etc.)kwargs (Dict[str, Any]) – Additional keyword arguments for file reading
- Return type:
DataFrame- Returns:
Dataset loaded from the specified file
Examples
>>> # Specify file_format parameter >>> df = read_dataset("data.csv", "csv") >>> >>> # Detect file_format automatically >>> df = read_dataset("data.csv")
- mutcleaner.cleaners.basic_cleaners.remap_mutation_positions_by_name(dataset, position_offsets=None, position_maps=None, name_column='name', mutation_column='mut_info', mutation_separator=',', strict=True)[source]#
Remap mutation positions using name-specific offsets or position maps.
Fixed offsets are suitable when source and target numbering systems differ by a constant value. Explicit position maps are suitable when residue correspondence is non-linear because of insertions, deletions, or other numbering differences.
When both rules are provided for the same name, an explicitly mapped position takes precedence over the fixed offset. Positions absent from the explicit map fall back to the fixed offset when one is available.
- Parameters:
dataset (
DataFrame) – Input dataset.position_offsets (
Optional[Dict[Any,int]]) – Mapping from protein names to fixed residue-position offsets.position_maps (
Optional[Dict[Any,Dict[int,int]]]) – Mapping from protein names to explicit source-to-target position maps.name_column (
str) – Column containing protein or dataset names.mutation_column (
str) – Column containing mutation descriptions.mutation_separator (
str) – Separator between individual mutations.strict (
bool) – Whether to raise an error for invalid mutation strings or positions missing from an explicit map when no fixed offset is available. If False, unsupported mutation tokens or unmapped positions are left unchanged.
- Return type:
DataFrame- Returns:
Dataset with remapped mutation positions.
- Raises:
ValueError – If required columns are missing, neither remapping rule is provided, or mutation positions cannot be remapped when
strict=True.
Examples
Create an example dataset:
>>> df = pd.DataFrame({ ... "name": ["proteinA", "proteinB"], ... "mut_info": ["S10T,F14V", "A5G"], ... })
Apply a fixed three-residue offset:
>>> result = remap_mutation_positions_by_name( ... df, ... position_offsets={"proteinA": 3}, ... ) >>> result["mut_info"].tolist() ['S13T,F17V', 'A5G']
Apply a non-linear explicit position map:
>>> result = remap_mutation_positions_by_name( ... df, ... position_maps={"proteinA": {10: 12, 14: 19}}, ... ) >>> result["mut_info"].tolist() ['S12T,F19V', 'A5G']
Combine a fixed offset with an explicit position map:
>>> result = remap_mutation_positions_by_name( ... df, ... position_offsets={"proteinA": 3}, ... position_maps={"proteinA": {14: 20}}, ... ) >>> result["mut_info"].tolist() ['S13T,F20V', 'A5G']
- mutcleaner.cleaners.basic_cleaners.replace_in_column(df, name_column, old, new='')[source]#
Replace or remove a literal substring in a specified DataFrame column.
This function performs a literal (non-regex) string replacement on the specified column. It replaces occurrences of a target substring (‘old’) with a new substring (‘new’). If ‘new’ is not provided, the target substring is removed.
- Parameters:
df (
DataFrame) – Input DataFrame containing at least one column with string identifiers.name_column (
str) – Name of the column on which to perform replacements.old (
str) – Non-empty substring to be replaced or removed.new (
str) – Replacement substring. If omitted or None, occurrences of ‘old’ will be removed. Defaults to “” (deletion).
- Return type:
DataFrame- Returns:
The DataFrame with the specified replacements applied.
- Raises:
ValueError – If ‘old’ is an empty string.
TypeError – If ‘df’ is not a pd.DataFrame or ‘old’ is not a str
KeyError – If ‘name_column’ does not exist in the DataFrame.
Examples
Remove the substring “.pdb”:
>>> import pandas as pd >>> df = pd.DataFrame({ ... 'name': ['prot1.pdb', 'prot1.pdb', 'prot1.pdb', 'prot2.pdb', 'prot2.pdb'], ... 'mut_info': ['A0S,Q1D', 'C2D', 'WT', 'E0F', 'WT'], ... 'mut_seq': ['SDCDEF', 'AQDDEF', 'AQCDEF', 'FGHIGHK', 'EGHIGHK'], ... 'score': [1.5, 2.0, 0.0, 3.0, 0.0] ... ) >>> replace_in_column(df, "name", ".pdb") name mut_info mut_seq score 0 prot1 A0S,Q1D SDCDEF 1.5 1 prot1 C2D AQDDEF 2.0 2 prot1 WT AQCDEF 0.0 3 prot2 E0F FGHIGHK 3.0 4 prot2 WT EGHIGHK 0.0
Replace “.pdb” with “.pross”:
>>> replace_in_column(df, "name", ".pdb", ".pross") name mut_info mut_seq score 0 prot1.pross A0S,Q1D SDCDEF 1.5 1 prot1.pross C2D AQDDEF 2.0 2 prot1.pross WT AQCDEF 0.0 3 prot2.pross E0F FGHIGHK 3.0 4 prot2.pross WT EGHIGHK 0.0
- mutcleaner.cleaners.basic_cleaners.split_columns(dataset, column_to_split, new_column_names, separator='_', max_splits=None, drop_original=False, fill_value='NaN', strip_whitespace=True, regex=False, custom_splitter=None)[source]#
Split a single column into multiple columns using a separator
This function splits values from one column into multiple new columns, with flexible splitting options.
- Parameters:
dataset (
DataFrame) – Input datasetcolumn_to_split (
str) – Name of the column to splitnew_column_names (
List[str]) – List of names for the new columnsseparator (
str) – Separator to use for splitting. Can be regex pattern if regex=True.max_splits (
Optional[int]) – Maximum number of splits to perform. If None, splits on all occurrences.drop_original (
bool) – Whether to drop the original column after splittingfill_value (
Optional[str]) – Value to use when split results have fewer parts than new_column_names. If None, uses NaN for missing parts.strip_whitespace (
bool) – Whether to strip whitespace from split resultsregex (
bool) – Whether to treat separator as a regex patterncustom_splitter (
Optional[Callable[[str],List[str]]]) – Custom function to split each value. Takes a string and returns a list of strings. If provided, ignores separator, max_splits, regex parameters.
- Return type:
DataFrame- Returns:
Dataset with the new split columns
Examples
Basic usage:
>>> df = pd.DataFrame({ ... 'mutation_id': ['BRCA1_100_A', 'TP53_200_T', 'EGFR_300_G'], ... 'score': [0.95, 0.87, 0.92] ... }) >>> result = split_columns( ... df, 'mutation_id', ['gene', 'position', 'mutation'], separator='_' ... ) Splitting column 'mutation_id' into ['gene', 'position', 'mutation']... Splitting using separator: '_' Successfully created split columns: ['gene', 'position', 'mutation'] >>> print(result[['gene', 'position', 'mutation']]) gene position mutation 0 BRCA1 100 A 1 TP53 200 T 2 EGFR 300 G
With max_splits:
>>> df = pd.DataFrame({ ... 'path': ['home/user/documents/file.txt', 'data/analysis/results.csv'] ... }) >>> result = split_columns( ... df, 'path', ['root', 'rest'], separator='/', max_splits=1 ... ) Splitting column 'path' into ['root', 'rest']... Splitting using separator: '/' Successfully created split columns: ['root', 'rest'] >>> print(result[['root', 'rest']]) root rest 0 home user/documents/file.txt 1 data analysis/results.csv
Handling insufficient splits with fill_value:
>>> df = pd.DataFrame({ ... 'incomplete': ['A_B', 'X_Y_Z', 'M'] ... }) >>> result = split_columns( ... df, 'incomplete', ['col1', 'col2', 'col3'], ... separator='_', fill_value='MISSING' ... ) Splitting column 'incomplete' into ['col1', 'col2', 'col3']... Splitting using separator: '_' Successfully created split columns: ['col1', 'col2', 'col3'] >>> print(result[['col1', 'col2', 'col3']]) col1 col2 col3 0 A B MISSING 1 X Y Z 2 M MISSING MISSING
Using regex separator:
>>> df = pd.DataFrame({ ... 'text': ['word1-word2_word3', 'itemA|itemB-itemC'] ... }) >>> result = split_columns( ... df, 'text', ['part1', 'part2', 'part3'], ... separator=r'[-_|]', regex=True ... ) Splitting column 'text' into ['part1', 'part2', 'part3']... Splitting using separator: '[-_|]' (regex) Successfully created split columns: ['part1', 'part2', 'part3'] >>> print(result[['part1', 'part2', 'part3']]) part1 part2 part3 0 word1 word2 word3 1 itemA itemB itemC
Custom splitter:
>>> def parse_coordinates(coord_str): ... # Parse "chr1:12345-67890" format ... parts = coord_str.replace(':', '_').replace('-', '_').split('_') ... return parts >>> df = pd.DataFrame({ ... 'coordinates': ['chr1:12345-67890', 'chr2:98765-43210'] ... }) >>> result = split_columns( ... df, 'coordinates', ['chromosome', 'start', 'end'], ... custom_splitter=parse_coordinates ... ) Splitting column 'coordinates' into ['chromosome', 'start', 'end']... Using custom splitter... 100%|█████████████████████████████| 2/2 [00:00<00:00, xx it/s] Successfully created split columns: ['chromosome', 'start', 'end'] >>> print(result[['chromosome', 'start', 'end']]) chromosome start end 0 chr1 12345 67890 1 chr2 98765 43210
Handling NaN values:
>>> df = pd.DataFrame({ ... 'data': ['A_B_C', None, 'X_Y'] ... }) >>> result = split_columns( ... df, 'data', ['col1', 'col2', 'col3'], separator='_' ... ) Splitting column 'data' into ['col1', 'col2', 'col3']... Splitting using separator: '_' Successfully created split columns: ['col1', 'col2', 'col3'] >>> print(result[['col1', 'col2', 'col3']]) col1 col2 col3 0 A B C 1 None NaN NaN 2 X Y NaN
- mutcleaner.cleaners.basic_cleaners.subtract_labels_by_wt(dataset, name_column, label_columns, mutation_column, wt_identifier='wt', suffix='_minus_wt', in_place=False, drop_wt_row=False)[source]#
For each group defined by
name_column, subtract the group’s WT label values (wheremutation_column == wt_identifier) from all rows’ label values.Returns two dataframes via the multi-output step: - successful: rows of groups where subtraction succeeded
(columns overwritten if
in_place=True; otherwise new columns<label><suffix>are added). Ifdrop_wt_row=True, WT rows are removed in this output.failed: one (or more) diagnostic rows per failed group, including an
error_messagecolumn describing the reason.
- Parameters:
dataset (
DataFrame)name_column (
str) – Grouping key column.label_columns (
Union[str,Sequence[str]]) – Numeric label column(s) to subtract by WT.mutation_column (
str) – Column that identifies the WT row withwt_identifier.wt_identifier (
str) – Token used to mark the WT row.suffix (
str) – Suffix for new columns (ignored ifin_place=True).in_place (
bool) – If True, overwrite original label columns with the deltas. If False, add new columns named<label><suffix>.drop_wt_row (
bool) – If True, drop WT rows from the successful output.
- Return type:
Tuple[DataFrame,DataFrame]- Returns:
Examples
>>> df = pd.DataFrame({ ... "name": ["A","A","B","B","B","C","C"], ... "mut" : ["wt","A0G","wt","K2R","L3F","S1N","T4A"], ... "y1" : [10.0, 12.0, 20.0, 22.0, 19.0, 8.0, 6.0], ... "y2" : [ 5.0, 4.0, 15.0, 10.0, 18.0, 3.0, 2.0], ... }) >>> successful, failed = subtract_labels_by_wt( ... dataset=df, ... name_column="name", ... label_columns=["y1", "y2"], ... mutation_column="mut", ... wt_identifier="wt", ... in_place=True, ... drop_wt_row=True, ... ) >>> successful name mut y1 y2 0 A A0G 2.0 -1.0 1 B K2R 2.0 -5.0 2 B L3F -1.0 3.0 >>> failed["failed"] name mut y1 y2 error_message 0 C S1N 8.0 3.0 No WT row (mutation_column == 'wt')
- mutcleaner.cleaners.basic_cleaners.validate_mutations(dataset, mutation_column='mut_info', format_mutations=True, mutation_sep=',', is_zero_based=False, mutation_type=None, alphabet=None, exclude_patterns=None, cache_results=True, num_workers=4)[source]#
Validate and format mutation information.
This function validates mutation strings, optionally formats them to a standard representation, and separates valid and invalid mutations into different datasets. It supports caching for improved performance on datasets with repeated mutations.
- Parameters:
dataset (
DataFrame) – Input dataset containing mutation informationmutation_column (
str) – Name of the column containing mutation informationformat_mutations (
bool) – Whether to format mutations to standard representationmutation_sep (
str) – Separator used to split multiple mutations in a single string (e.g., ‘A123B,C456D’)is_zero_based (
bool) – Whether origin mutation positions are zero-basedmutation_type (str, optional) – Type of mutation (e.g., ‘CodonMutation’, ‘AminoAcidMutation’)
alphabet (BaseAlphabet, optional) – Alphabet to use for mutation validation
exclude (Union[str, List[str], callable, None], default=None) – Patterns to exclude from validation. Can be: - A regex pattern string (e.g., r’^WT$|^wildtype$’) - A list of exact strings to match (e.g., [‘WT’, ‘wildtype’, ‘UNKNOWN’]) - A list containing both regex patterns (starting with ‘regex:’) and exact strings - A callable that takes a string value and returns True if it should be excluded - None to validate all values
cache_results (
bool) – Whether to cache formatting results for performancenum_workers (
int) – Number of parallel workers for processing, set to -1 for all available CPUs
- Return type:
Tuple[DataFrame,DataFrame]- Returns:
(successful_dataset, failed_dataset) - datasets with valid and invalid mutations
Examples
>>> import pandas as pd >>> df = pd.DataFrame({ ... 'name': ['protein1', 'protein1', 'protein2'], ... 'mut_info': ['A123S', 'C456D,E789F', 'InvalidMut'], ... 'score': [1.5, 2.3, 3.7] ... }) >>> successful, failed = validate_mutations(df, mutation_column='mut_info', mutation_sep=',') >>> print(len(successful)) 2 >>> print(successful['mut_info'].tolist()) # Formatted mutations ['A123S', 'C456D,E789F'] >>> print(len(failed)) 1 >>> print(failed['failed']['error_message'].iloc[0]) # Error message for failed mutation 'ValueError: No valid mutations could be parsed...' >>> # Exclude patterns >>> df = pd.DataFrame({ ... 'name': ['protein1', 'protein1', 'protein2', 'protein3', 'protein4'], ... 'mut_info': ['A123S', 'C456D,E789F', 'WT', 'wildtype', 'UNKNOWN'], ... 'score': [1.5, 2.3, 3.7, 4.1, 5.2] ... }) >>> >>> # Exclude exact string matches >>> successful, failed = validate_mutations( ... df, ... mutation_column='mut_info', ... exclude_patterns=['WT', 'wildtype', 'UNKNOWN'] ... ) >>> >>> # Exclude using regex pattern >>> successful, failed = validate_mutations( ... df, ... mutation_column='mut_info', ... exclude_patterns=r'^(WT|wildtype|UNKNOWN)$' ... ) >>> >>> # Mixed approach: regex patterns (prefixed with 'regex:') and exact strings >>> successful, failed = validate_mutations( ... df, ... mutation_column='mut_info', ... exclude_patterns=['regex:^WT$', 'regex:.*type.*', 'UNKNOWN'] ... ) >>> >>> # Using a custom function >>> exclude_func = lambda x: str(x).upper() in ['WT', 'WILDTYPE'] or 'UNKNOWN' in str(x) >>> successful, failed = validate_mutations( ... df, ... mutation_column='mut_info', ... exclude_patterns=exclude_func ... ) >>> successful name mut_info score 0 protein2 WT 3.7 1 protein3 wildtype 4.1 2 protein4 UNKNOWN 5.2 3 protein1 A122S 1.5 4 protein1 C455D,E788F 2.3