Ваша проблема состоит из двух частей:
1- Нахождение максимального значения каждой строки
2- Выбор максимального столбца каждой строки со значениями, найденными на первом шаге
Вы можете легко использовать функцию lookup . Первый аргумент - это поиск максимального столбца в строках (первый шаг), а второй - выбор (второй шаг)
df2.lookup(range(len(df1)), df1.idxmax()) #output => array(['b', 'd', 'i'], dtype=object)
Если массив не работает для вас, вы также можете создать фрейм данных из этих значений, просто передав его в pd.DataFrame:
pd.DataFrame(df2.lookup(range(len(df1)), df1.idxmax()))
Одна хорошая особенность этого решения - избегать петель, которые делают его эффективным.