@export
def add_process_features(input_frame: pd.DataFrame, path_separator: str=None, force: bool=False) -> pd.DataFrame:
    '\n    Add numerical features based on patterns of command line and process name.\n\n    Parameters\n    ----------\n    input_frame : pd.DataFrame\n        The input dataframe\n    path_separator : str, optional\n        Path separator. If not supplied, try to determine\n        from \'NewProcessName\' column of first 10 rows\n        (the default is None)\n    force : bool, optional\n        Forces re-calculation of feature columns even if they\n        already exist (the default is False)\n\n    Returns\n    -------\n    pd.DataFrame\n        Copy of the dataframe with the additional numeric features\n\n    Notes\n    -----\n    Features added:\n\n    - processNameLen: length of process file name (inc path)\n    - processNameTokens: the number of elements in the path\n    - processName: the process file name (minus path)\n    - commandlineTokens: number of space-separated tokens in the command line\n    - commandlineLen: length of the command line\n    - commandlineLogLen: log10 length of commandline\n    - isSystemSession: 1 if session Id is 0x3e7 for Windows or -1 for Linux\n    - commandlineTokensFull: counts number of token separators in commandline\n      [\\\\s\\-\\\\/\\.,"\\\'\\|&:;%$()]\n    - pathScore: sum of ord() value of characters in path\n    - pathLogScore: log10 of pathScore\n    - commandlineScore: sum of ord() value of characters in commandline\n    - commandlineLogScore: log10 of commandlineScore\n\n    '
    output_df = input_frame.copy()
    if (('NewProcessName' in output_df) and ('CommandLine' in output_df)):
        output_df[['NewProcessName', 'CommandLine']] = output_df[['NewProcessName', 'CommandLine']].fillna(value='')
    if (path_separator is None):
        sample_df = output_df.head(10)
        lx_path = len(sample_df[sample_df['NewProcessName'].str.contains('/')])
        path_separator = ('/' if lx_path else '\\')
    if ('NewProcessName' in output_df):
        _add_processname_features(output_df, force, path_separator)
    if ('CommandLine' in output_df):
        _add_commandline_features(output_df, force)
    if (('SubjectLogonId' in output_df) and (('isSystemSession' not in output_df) or force)):
        output_df['isSystemSession'] = output_df['SubjectLogonId'].isin(['0x3e7', '-1'])
    return output_df
Add numerical features based on patterns of command line and process name.

Parameters
----------
input_frame : pd.DataFrame
    The input dataframe
path_separator : str, optional
    Path separator. If not supplied, try to determine
    from 'NewProcessName' column of first 10 rows
    (the default is None)
force : bool, optional
    Forces re-calculation of feature columns even if they
    already exist (the default is False)

Returns
-------
pd.DataFrame
    Copy of the dataframe with the additional numeric features

Notes
-----
Features added:

- processNameLen: length of process file name (inc path)
- processNameTokens: the number of elements in the path
- processName: the process file name (minus path)
- commandlineTokens: number of space-separated tokens in the command line
- commandlineLen: length of the command line
- commandlineLogLen: log10 length of commandline
- isSystemSession: 1 if session Id is 0x3e7 for Windows or -1 for Linux
- commandlineTokensFull: counts number of token separators in commandline
  [\\s\-\\/\.,"\'\|&:;%$()]
- pathScore: sum of ord() value of characters in path
- pathLogScore: log10 of pathScore
- commandlineScore: sum of ord() value of characters in commandline
- commandlineLogScore: log10 of commandlineScore
@export
def add_process_features(input_frame: pd.DataFrame, path_separator: str=None, force: bool=False) -> pd.DataFrame:
    '\n    Add numerical features based on patterns of command line and process name.\n\n    Parameters\n    ----------\n    input_frame : pd.DataFrame\n        The input dataframe\n    path_separator : str, optional\n        Path separator. If not supplied, try to determine\n        from \'NewProcessName\' column of first 10 rows\n        (the default is None)\n    force : bool, optional\n        Forces re-calculation of feature columns even if they\n        already exist (the default is False)\n\n    Returns\n    -------\n    pd.DataFrame\n        Copy of the dataframe with the additional numeric features\n\n    Notes\n    -----\n    Features added:\n\n    - processNameLen: length of process file name (inc path)\n    - processNameTokens: the number of elements in the path\n    - processName: the process file name (minus path)\n    - commandlineTokens: number of space-separated tokens in the command line\n    - commandlineLen: length of the command line\n    - commandlineLogLen: log10 length of commandline\n    - isSystemSession: 1 if session Id is 0x3e7 for Windows or -1 for Linux\n    - commandlineTokensFull: counts number of token separators in commandline\n      [\\\\s\\-\\\\/\\.,"\\\'\\|&:;%$()]\n    - pathScore: sum of ord() value of characters in path\n    - pathLogScore: log10 of pathScore\n    - commandlineScore: sum of ord() value of characters in commandline\n    - commandlineLogScore: log10 of commandlineScore\n\n    '
    output_df = input_frame.copy()
    if (('NewProcessName' in output_df) and ('CommandLine' in output_df)):
        output_df[['NewProcessName', 'CommandLine']] = output_df[['NewProcessName', 'CommandLine']].fillna(value=)
    if (path_separator is None):
        sample_df = output_df.head(10)
        lx_path = len(sample_df[sample_df['NewProcessName'].str.contains('/')])
        path_separator = ('/' if lx_path else '\\')
    if ('NewProcessName' in output_df):
        _add_processname_features(output_df, force, path_separator)
    if ('CommandLine' in output_df):
        _add_commandline_features(output_df, force)
    if (('SubjectLogonId' in output_df) and (('isSystemSession' not in output_df) or force)):
        output_df['isSystemSession'] = output_df['SubjectLogonId'].isin(['0x3e7', '-1'])
    return output_df