SequenceFeature.aa_composition

SequenceFeature.aa_composition(df_seq, list_parts=None, return_df=False)[source]

Create the amino-acid-composition (AAC) baseline matrix for given sequences.

Builds the no-positional-split amino-acid-composition baseline featurization: for each sequence the requested Parts are concatenated into one span and the fraction of each of the 20 canonical amino acids over that span is computed, yielding the (n_seq, 20) matrix X. The 20 columns follow the canonical order ut.LIST_CANONICAL_AA (A, C, D, ..., Y) so column order is stable, and each row sums to 1. Unlike SequenceFeature.feature_matrix(), which averages scales over a specific Part-Split, this method carries no positional information — it is a plain residue frequency count.

Application. Use this to build a baseline feature set for a prediction model: fit the same classifier on this composition X and on a CPP feature_matrix() and compare the scores to show how much the positional Part-Split-Scale features add over a plain amino-acid frequency encoding (the “AAC baseline vs CPP” comparison). It is not a positional feature set — reach for CPP when you need where-along-the-sequence information.

Added in version 1.1.0.

Parameters:
  • df_seq (pd.DataFrame, shape (n_samples, n_seq_info)) – DataFrame containing an entry column with unique protein identifiers and sequence information in a distinct format: Position-based, Part-based, Sequence-based, or Sequence-TMD-based (the same input accepted by SequenceFeature.get_df_parts()).

  • list_parts (str or list of str, optional) – Names of the sequence parts to count over (see SequenceFeature for valid parts). If None (default), the whole TMD-JMD span jmd_n + tmd + jmd_c (the tmd_jmd part) is used. Multiple parts are concatenated per sequence before counting.

  • return_df (bool, default=False) – If True, return a labeled pd.DataFrame (rows indexed like df_parts, one column per canonical amino acid) instead of a plain numpy array.

Returns:

X – Amino-acid-composition matrix containing, per sequence, the fraction of each of the 20 canonical amino acids over the span residues (columns in ut.LIST_CANONICAL_AA order). Returned as a pd.DataFrame (amino-acid letters as columns) when return_df=True.

Return type:

array-like, shape (n_samples, 20)

Notes

  • Missing / non-canonical residues: only the 20 canonical amino acids are counted. Gap symbols ('-') and any other non-canonical symbol (e.g. 'X') are dropped per the package convention, so the fractions are taken over the canonical residues only and sum to 1.

  • A sequence whose span has no canonical residue (empty span, or all residues non-canonical) yields an all-NaN row; a UserWarning naming the count is emitted when verbose=True.

  • This is a no-positional-split composition only; positional splits remain the job of CPP.

See also

Examples

SequenceFeature().aa_composition() builds a baseline feature set for a prediction model. For each sequence it counts the fraction of each of the 20 canonical amino acids over a span, giving the (n_seq, 20) matrix X — the sequence’s amino-acid composition (AAC), with no positional information. Its purpose is comparison: fit the same classifier on this X and on a :class:CPP feature_matrix, and compare the scores to see how much CPP’s positional Part-Split-Scale features add over a plain amino-acid frequency encoding. Here we load the DOM_GSEC example dataset (see [Breimann25]):

import aaanalysis as aa
aa.options["verbose"] = False
df_seq = aa.load_dataset(name="DOM_GSEC")
sf = aa.SequenceFeature()

By default (list_parts=None) the whole TMD-JMD span (jmd_n + tmd + jmd_c) is used. Only the 20 canonical amino acids are counted; gap symbols ('-') and other non-canonical residues (e.g. 'X') are dropped, so each row sums to 1:

X = sf.aa_composition(df_seq=df_seq)
print(f"n samples: {X.shape[0]}")
print(f"n amino acids: {X.shape[1]}")
print(f"Shape of X: {X.shape}")
print(f"Row sums (first 3): {X[:3].sum(axis=1)}")
n samples: 126
n amino acids: 20
Shape of X: (126, 20)
Row sums (first 3): [1. 1. 1.]

With return_df=True the matrix is returned as a labeled pd.DataFrame (rows indexed by protein entry, one column per canonical amino acid, in A, C, D, ..., Y order):

df_aa_composition = sf.aa_composition(df_seq=df_seq, return_df=True)
aa.display_df(df_aa_composition, n_rows=10, show_shape=True)
DataFrame shape: (126, 20)
  A C D E F G H I K L M N P Q R S T V W Y
entry                                        
P05067 0.069767 0.000000 0.023256 0.023256 0.023256 0.116279 0.046512 0.139535 0.093023 0.069767 0.046512 0.023256 0.000000 0.023256 0.000000 0.046512 0.069767 0.162791 0.000000 0.023256
P14925 0.046512 0.000000 0.023256 0.023256 0.046512 0.069767 0.000000 0.093023 0.069767 0.162791 0.023256 0.000000 0.046512 0.000000 0.046512 0.093023 0.069767 0.162791 0.023256 0.000000
P70180 0.093023 0.023256 0.000000 0.069767 0.069767 0.139535 0.000000 0.069767 0.069767 0.116279 0.023256 0.000000 0.023256 0.000000 0.069767 0.069767 0.046512 0.069767 0.000000 0.046512
Q03157 0.069767 0.000000 0.000000 0.023256 0.000000 0.186047 0.000000 0.069767 0.069767 0.209302 0.023256 0.000000 0.046512 0.000000 0.046512 0.139535 0.046512 0.046512 0.000000 0.023256
Q06481 0.093023 0.000000 0.023256 0.023256 0.023256 0.046512 0.023256 0.139535 0.023256 0.162791 0.023256 0.000000 0.000000 0.023256 0.069767 0.139535 0.046512 0.116279 0.000000 0.023256
P35613 0.069767 0.000000 0.023256 0.069767 0.046512 0.023256 0.023256 0.139535 0.046512 0.162791 0.000000 0.000000 0.046512 0.000000 0.093023 0.023256 0.046512 0.139535 0.023256 0.023256
P35070 0.023256 0.093023 0.023256 0.000000 0.046512 0.069767 0.023256 0.139535 0.046512 0.139535 0.023256 0.000000 0.023256 0.023256 0.139535 0.000000 0.023256 0.139535 0.000000 0.023256
P09803 0.093023 0.000000 0.000000 0.023256 0.023256 0.116279 0.000000 0.139535 0.023256 0.325581 0.000000 0.000000 0.046512 0.023256 0.069767 0.000000 0.023256 0.093023 0.000000 0.000000
P19022 0.093023 0.023256 0.023256 0.023256 0.023256 0.093023 0.000000 0.186047 0.069767 0.162791 0.046512 0.000000 0.000000 0.023256 0.093023 0.000000 0.023256 0.093023 0.023256 0.000000
P16070 0.116279 0.046512 0.000000 0.023256 0.000000 0.046512 0.000000 0.139535 0.069767 0.186047 0.000000 0.023256 0.069767 0.046512 0.093023 0.046512 0.023256 0.046512 0.023256 0.000000

Use list_parts to count only over selected sequence parts (concatenated per sequence). For example, restrict the baseline to the TMD:

X_tmd = sf.aa_composition(df_seq=df_seq, list_parts="tmd")
print(f"Shape of X (TMD only): {X_tmd.shape}")
Shape of X (TMD only): (126, 20)

Multiple parts are concatenated per sequence before counting (here the two juxtamembrane domains):

X_jmd = sf.aa_composition(df_seq=df_seq, list_parts=["jmd_n", "jmd_c"])
print(f"Shape of X (JMD_N + JMD_C): {X_jmd.shape}")
Shape of X (JMD_N + JMD_C): (126, 20)