Pandas DataFrame.sort_values() new method to exclude by row name
When using pandas leverage on functions in API almost every function is vectorized.
You can break down your problem into categories.

If fixed is None just sort w.r.t given column_names.
Else sort w.r.t given column_names but filter filter fixed indices.
insert fixed at previous positions.

def sort_values(df, column_names, ascending=False, fixed=None):
    if fixed is None:
        return df.sort_values(column_names, ascending=ascending)
    idx = df.index.get_indexer(fixed).tolist()
    s_df = df.sort_values(column_names, ascending=ascending).T
    keep_cols = s_df.columns.difference(fixed, sort=False)
    out = s_df[keep_cols]
    for (loc, name) in zip(idx, fixed):
        out.insert(loc, name, s_df[name])
    return out.T

Note: fixed should be a list.
Example runs:
fixed = ['rank3']
sort_values(df, ['marks'], ascending=False, fixed=fixed)

#        Name marks
# rank2  Jack    30
# rank1   Tom    10
# rank3  nick    50  # rank3 position fixed.
# rank4  juli     5

fixed = ['rank2', 'rank3']
sort_values(df, ['marks'], ascending=True, fixed=fixed) # ascending order.

# sorted in ascending order
#        Name marks
# rank4  juli     5
# rank2  Jack    30 # rank2 position fixed
# rank3  nick    50 # rank3 position fixed
# rank1   Tom    10

Code Review

PEP-8 Violations

E501 - Lines longer than 79 characters. You have many lines with length greater than 79 characters.



# Examples
original_positions = {name: position for position, name in enumerate(df.index.values) if name in fixed_categories}
# Can be refactored as below 
original_positions = {
    name: position
    for position, name in enumerate(df.index.values)
    if name in fixed_categories
}

original_positions = dict(sorted(original_positions.items(), key=operator.itemgetter(1), reverse=True))
# Can be refactored as below
original_positions = dict(
    sorted(
        original_positions.items(), key=operator.itemgetter(1), reverse=True
    )
)


You can use pep8online* to check if your code is in accordance with PEP-8 standard.
You can use black* (code formatting tool)
black --line-length 79 your_file.py


* I'm not affiliated to pep8online and black.