Как правильно подсчитать количество минут поверх заданного тарифа - pandas

Подскажите, пожалуйста, как можно подсчитать правильно количество минут поверх заданного тарифа и записать результат в один столбец?

Задача следующая : есть таблица с данными по количеству клиентов в телеком компании, а также их тарифами и количеством минут, которые операторы тратили за конкретный месяц. Необходимо просчитать количество исходящих минут по внутренним звонкам и сравнить, был ли превышен лимит у того или иного клиента. У меня сложность встала в том, что я логически понимаю как подсчитать всё это, но вот как выстроить условия для трех разных тарифов и записать всю в один столбец - тупняк полный. Помогите разобраться, пожалуйста.

Таблица, в которую планирую добавлять данные по следующим критериям

введите сюда описание изображения

Пример моего кода:

internal_over_limit = ((df_revenue_month['direction']=='out') &
                       (df_revenue_month['internal']==True) &
                       (df_revenue_month['tariff_plan']=='C') &
                       (df_revenue_month['total_minutes']>0))

df_revenue_month.loc[internal_over_limit, 'minutes_internal_over_limit'] = df_revenue_month['total_minutes'] - 0    
df_revenue_month['minutes_internal_over_limit'] = df_revenue_month['minutes_internal_over_limit'].fillna(0)    
df_revenue_month.head(5) 

Глобально - он выполняет мою цель, но лишь частично. У каждого тарифного плана свой лимит, который нужно отсчитывать и выводить в новый столбец данные ТОЛЬКО поверх лимита. А - 2000, B - 500, С - 0.

Направьте, пожалуйста. Заранее спасибо!


Ответы (1 шт):

Автор решения: Алексей Р

Описание вопроса неполное - нет воспроизводимого фрагмента исходных данных и отсутствует образец ожидаемого результата, который должен получаться после обработки данных. Сделал, как понял. Может, угадал, а может, и нет.
По сути решения. Сначала нужно отфильтровать фрейм df = df[df.direction.eq('out') & df.internal]. Далее группируем по id и plan и применяем transform(sum), суммируя все минуты по каждой группе. После чего отнимаем Series c плановыми минутами, полученный путем замены букв плана на плановые лимиты, заданные в словаре limits. Результат обрабатываем методом mask, заменяя отрицательные числа на 0.

df = pd.DataFrame({'id': [123] * 3 + [456] * 3, 'plan': ['B'] * 3 + ['A'] * 3, 'direction': ['in', 'out'] * 3, 'internal': [False, True] * 3, 'minutes': [200, 300, 400, 100, 200, 3000]})
limits = {'A': 2000, 'B': 500, 'C': 0}
print(df)
df = df[df.direction.eq('out') & df.internal]
df['over'] = (df.groupby(['id', 'plan']).minutes.transform(sum) - df.plan.replace(limits)).mask(lambda x: x < 0, 0)
print(df)
    id plan direction  internal  minutes
0  123    B        in     False      200
1  123    B       out      True      300
2  123    B        in     False      400
3  456    A       out      True      100
4  456    A        in     False      200
5  456    A       out      True     3000
    id plan direction  internal  minutes  over
1  123    B       out      True      300     0
3  456    A       out      True      100  1100
5  456    A       out      True     3000  1100
→ Ссылка