np.where, np.select, Series.mask/where, булевы выражения и .clip закрывают большинство ветвлений быстрее, чем apply(axis=1).
Разбор
np.select(conds, choices, default=) для многих веток.
- Читаемость: именованные промежуточные маски.
- Для строковых правил — векторизованные
.str + where.
- Профилируйте, если всё же нужен apply.
Пример
df["tier"] = np.select([df.x >= 100, df.x >= 50], ["A", "B"], default="C")
Итог
Условия считайте векторно через where/select, не построчным apply.