How to get the indexes of smallest value per row in a DF, as column index and not column name?
df.apply over axis 1 is generally avoid for performance issues. When should I (not) want to use pandas .apply() in my code
1. pd.Index.get_indexer
cols = df.idxmin(axis=1)
idx = df.columns.get_indexer(cols) # return a numpy array
idx_series = pd.Series(idx, index=df.index)
# Here, index=df.index is important when your DataFrame has custom index values

print(idx_series)
0    0
1    1
2    0
3    2
4    2
dtype: int64

2. df.to_numpy and np.ndarray.argmin
idx = df.to_numpy().argmin(axis=1) # returns numpy array
idx_series = pd.Series(idx, index=df.index)
print(idx_series)

0    0
1    1
2    0
3    2
4    2
dtype: int64


Some timeit benchs
from datetime import timedelta
from timeit import timeit

if __name__ == '__main__':

    setup = &quot;&quot;&quot;
import pandas as pd
import numpy as np
from random import randrange
total = 10000
df = pd.DataFrame({
        'col1': [randrange(10000) for i in range(total)],
        'col2': [randrange(10000) for i in range(total)],
        'col3': [randrange(10000) for i in range(total)],
        'col4': [randrange(10000) for i in range(total)],
        'col5': [randrange(10000) for i in range(total)],
        'col6': [randrange(10000) for i in range(total)],
        'col7': [randrange(10000) for i in range(total)],
    })
    &quot;&quot;&quot;

    for stmt in [&quot;pd.Series(df.to_numpy().argmin(axis=1), index=df.index)&quot;,
                 &quot;pd.Series(df.columns.get_indexer(df.idxmin(axis=1)), index=df.index)&quot;,
                 &quot;df.apply(np.argmin, axis=1)&quot;]:
        t = timeit(stmt=stmt, setup=setup, number=20)
        print(f&quot;{str(timedelta(seconds=t)):20s}{stmt}&quot;)


# Results
0:00:00.012226      pd.Series(df.to_numpy().argmin(axis=1), index=df.index)
0:00:00.408151      pd.Series(df.columns.get_indexer(df.idxmin(axis=1)), index=df.index)
0:00:23.908125      df.apply(np.argmin, axis=1)