Дневная доля отмен без забаненных клиентов и водителей
trips(id, client_id, driver_id, city_id, status, request_at) со status из completed, cancelled_by_driver, cancelled_by_client; users(users_id, banned, role). Для каждого дня с 2013-10-01 по 2013-10-03 верните долю отмен среди поездок, где и клиент, и водитель не забанены: отменённые такие поездки / все такие поездки за день, округлённую до 2 знаков.
import pandas as pd
def cancellation_rate(trips: pd.DataFrame, users: pd.DataFrame) -> pd.DataFrame:
# ваш код здесь
Напишите реализацию.
Фильтруют до поездок, где обе стороны не забанены, затем берут дневное среднее флага отмены. Объединяют users дважды — по client_id и по driver_id — чтобы привязать бан-статус каждой стороны, оставляют строки, где ни один не забанен, ограничивают диапазоном дат и группируют по дню.
- ✗Проверять бан только клиента, но не водителя
- ✗Пропускать фильтр банов вовсе
- ✗Считать отменой только один тип отмены
- →Зачем здесь два отдельных объединения с users?
- →Как str.startswith обрабатывает оба типа отмены сразу?
Attach both parties' ban status via two merges, keep trips where neither is banned, then take the daily mean of the cancelled flag.
import pandas as pd
def cancellation_rate(trips: pd.DataFrame, users: pd.DataFrame) -> pd.DataFrame:
ban = users.set_index('users_id')['banned']
t = trips[
(trips['client_id'].map(ban) == 'No') &
(trips['driver_id'].map(ban) == 'No') &
(trips['request_at'].between('2013-10-01', '2013-10-03'))
].copy()
t['cancelled'] = t['status'].str.startswith('cancelled')
out = (t.groupby('request_at')['cancelled'].mean().round(2)
.reset_index(name='cancellation_rate'))
return out
Mapping client_id and driver_id through the ban lookup enforces that both parties are unbanned. status.str.startswith('cancelled') flags both cancelled_by_driver and cancelled_by_client, so the per-day mean is the cancellation rate. For 2013-10-01..03 the rates come out 0.33, 0.00, 0.50.