code: def molecular_descriptors(
      df: pd.DataFrame, mols_column_name: Hashable
  ) -> pd.DataFrame:
      """Convert a column of RDKIT mol objects into a Pandas DataFrame
      of molecular descriptors.
  
      Returns a new dataframe without any of the original data. This is
      intentional to leave the user only with the data requested.
  
      This method does not mutate the original DataFrame.
  
      The molecular descriptors are from the `rdkit.Chem.rdMolDescriptors`:
  
      ```text
      Chi0n, Chi0v, Chi1n, Chi1v, Chi2n, Chi2v, Chi3n, Chi3v,
      Chi4n, Chi4v, ExactMolWt, FractionCSP3, HallKierAlpha, Kappa1,
      Kappa2, Kappa3, LabuteASA, NumAliphaticCarbocycles,
      NumAliphaticHeterocycles, NumAliphaticRings, NumAmideBonds,
      NumAromaticCarbocycles, NumAromaticHeterocycles, NumAromaticRings,
      NumAtomStereoCenters, NumBridgeheadAtoms, NumHBA, NumHBD,
      NumHeteroatoms, NumHeterocycles, NumLipinskiHBA, NumLipinskiHBD,
      NumRings, NumSaturatedCarbocycles, NumSaturatedHeterocycles,
      NumSaturatedRings, NumSpiroAtoms, NumUnspecifiedAtomStereoCenters,
      TPSA.
      ```
  
      Examples:
          Functional usage
  
          >>> import pandas as pd
          >>> import janitor.chemistry
          >>> df = pd.DataFrame({"smiles": ["O=C=O", "CCC(=O)O"]})
          >>> mol_desc = (
          ...     janitor.chemistry.molecular_descriptors(
          ...         df=df.smiles2mol('smiles', 'mols'),
          ...         mols_column_name='mols'
          ...     )
          ... )
          >>> mol_desc.TPSA
          0    34.14
          1    37.30
          Name: TPSA, dtype: float64
  
          Method chaining usage
  
          >>> import pandas as pd
          >>> import janitor.chemistry
          >>> df = pd.DataFrame({"smiles": ["O=C=O", "CCC(=O)O"]})
          >>> mol_desc = (
          ...     df.smiles2mol('smiles', 'mols')
          ...     .molecular_descriptors(mols_column_name='mols')
          ... )
          >>> mol_desc.TPSA
          0    34.14
          1    37.30
          Name: TPSA, dtype: float64
  
          If you wish to join the molecular descriptors back into the original
          dataframe, this can be accomplished by doing a `join`,
          because the indices are preserved:
  
          >>> joined = df.join(mol_desc)
          >>> len(joined.columns)
          41
  
      Args:
          df: A pandas DataFrame.
          mols_column_name: The name of the column that has the RDKIT mol
              objects.
  
      Returns:
          A new pandas DataFrame of molecular descriptors.
      """
      descriptors = [
          CalcChi0n,
          CalcChi0v,
          CalcChi1n,
          CalcChi1v,
          CalcChi2n,
          CalcChi2v,
          CalcChi3n,
          CalcChi3v,
          CalcChi4n,
          CalcChi4v,
          CalcExactMolWt,
          CalcFractionCSP3,
          CalcHallKierAlpha,
          CalcKappa1,
          CalcKappa2,
          CalcKappa3,
          CalcLabuteASA,
          CalcNumAliphaticCarbocycles,
          CalcNumAliphaticHeterocycles,
          CalcNumAliphaticRings,
          CalcNumAmideBonds,
          CalcNumAromaticCarbocycles,
          CalcNumAromaticHeterocycles,
          CalcNumAromaticRings,
          CalcNumAtomStereoCenters,
          CalcNumBridgeheadAtoms,
          CalcNumHBA,
          CalcNumHBD,
          CalcNumHeteroatoms,
          CalcNumHeterocycles,
          CalcNumLipinskiHBA,
          CalcNumLipinskiHBD,
          CalcNumRings,
          CalcNumSaturatedCarbocycles,
          CalcNumSaturatedHeterocycles,
          CalcNumSaturatedRings,
          CalcNumSpiroAtoms,
          CalcNumUnspecifiedAtomStereoCenters,
          CalcTPSA,
      ]
      descriptors_mapping = {
          f.__name__.strip("Calc"): f for f in descriptors
      }
  
      feats = dict()
      for name, func in descriptors_mapping.items():
          feats[name] = [func(m) for m in df[mols_column_name]]
      return pd.DataFrame(feats)
  
file_path: pyjanitor/janitor/chemistry.py
imports: from typing import Hashable, Literal, Optional
  import numpy
  import pandas
  import pandas_flavor
  from .utils import deprecated_alias, import_message
label_desc: Use image node_id 3 for calling a global function with example usage: molecular_descriptors(df, mols_column_name) and returns: pd