Собесов

ВК Junior: DPU и NPU по транзакциям из Excel

PythonExcel и pandasЛёгкаяJunior

Условие

Дан массив из 5385 транзакций. Для прошедших платежей (Financial Status = "Charged") посчитать на каждый день:

  • DPU (Daily Paying Users) — количество уникальных платящих пользователей за день.
  • NPU (New Paying Users) — количество впервые заплативших пользователей за день.

Решение

Pandas

import pandas as pd
 
df = pd.read_excel('test_excel.xlsx')
df = df[df['Financial Status'] == 'Charged'].copy()
df['date'] = pd.to_datetime(df['Date']).dt.date
 
# DPU
dpu = df.groupby('date')['user_id'].nunique().rename('DPU')
 
# NPU: дата первого платежа каждого пользователя
first_pay = df.groupby('user_id')['date'].min().reset_index(name='first_date')
npu = first_pay.groupby('first_date').size().rename('NPU')
 
result = pd.concat([dpu, npu], axis=1).fillna(0).astype(int).reset_index()
result.to_excel('result.xlsx', index=False)

Только Excel-формулы

Если ограничено Excel:

  • DPU = на отдельном листе свод: =COUNTIFS(date_col, A2, fin_status_col, "Charged") с уникальными — лучше Power Pivot/UNIQUE+COUNTIFS.
  • NPU: вспомогательная колонка is_first=IF(COUNTIFS(user_col, B2, date_col, "<"&A2, fin_status_col, "Charged")=0, 1, 0). Затем SUMIFS(is_first, date_col, ...).

Подводные камни

  1. Возвраты: если транзакция отменена — её счёт DPU считаться не должен. Фильтр Charged это решает.
  2. Один пользователь — несколько платежей в день: DPU считает уникальных, простой COUNT неверен.
  3. NPU должен быть < DPU; сумма NPU за весь период = число уникальных пользователей.
  4. Дата может быть с временем — обязательно .dt.date или DATE().
  5. На бесконечно длинной истории NPU в первый день может «съесть» всех — нужен корректный horizon.

Эталонный ответ

DPU = nunique(user) по дням; NPU = группировка по дате первого платежа каждого user_id.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти