Как посчитать пользователей, попавших в две группы из двух?
Пробую решать разные задачки в качестве самообразования.
Есть DataFrame:
orders = pd.read_csv('orders.csv')
Он содержит столбцы:
print(orders.head())
transaction_id visitor_id date revenue group
0 3667963787 3312258926 2019-08-15 1650 B
1 2804400009 3642806036 2019-08-15 730 B
2 2961555356 4069496402 2019-08-15 400 A
3 3797467345 1196621759 2019-08-15 9759 B
4 2282983706 2322279887 2019-08-15 2308 B
- transaction_id — идентификатор заказа;
- visitor_id — идентификатор пользователя, совершившего заказ;
- date — дата, когда был совершён заказ;
- revenue — выручка заказа;
- group — группа A/B-теста, в которую попал заказ.
Нужно проверить сколько пользователей попали одновременно в обе группы и затем удалить их из таблицы.
Проблема начинается с поиска.
Попробовано:
- создание срезов по группам и их объединение. Не работает.
- группировка по 'visitor_id' и 'group' с поиском количества заказов. Но дальше с этой таблицей не получается что-либо сделать.
Затуп конкретный. Очень прошу помочь. Для меня это в новинку.
Спасибо.
Ответы (3 шт):
После того как вы сделали группировку по 'visitor_id' и 'group', вы можете добавить соответствующую колонку в датафрейм и затем отобрать по этому признаку. Покажу на следующем примере
df = pd.DataFrame(data=[[1,'A'], [1, 'B'], [2, 'A'], [2, 'B'], [3, 'A'], [4, 'B']], columns=['id','c'])
Теперь группируем, как это делали вы
countGroups = df.groupby('id')['c'].nunique()
Мерджим, обратите внимание, что это повлияло на названия колонок
df = df.merge(countGroups, on=["id", "id"])
А теперь мы делаем обратную операцию, мы не удаляем, а выбираем те колонки, которые нам нужны по условию
df[df['c_y'] == 1]
Если вас в образовательных целях интересует как именно удалять по условию, то похожий ответ нашла тут, однако мне показалось, что подход выше проще.
При необходимости можно будет удалить лишний столбец и переименовать колонки.
С двумя группами это сделать довольно просто. Если у вас есть датафрейм df, например:
id group
0 1 a
1 2 a
2 3 b
3 3 a
4 2 b
5 1 a
то сделать можно так:
mask = df.loc[df["group"]=="a", "id"].isin(df.loc[df["group"]=="b", "id"])
res = df.drop(mask[mask].index)
тогда res будет:
id group
0 1 a
2 3 b
4 2 b
5 1 a
Проверить, сколько пользователей попали одновременно в обе группы можно так:
orders.groupby('visitor_id').agg({'group' : 'nunique'}).query('group>1').count()
Далее создаем список пользователей с уникальными visitor_id:
double_users = orders.groupby('visitor_id').agg({'group' : 'nunique'})
.reset_index().query('group>1')['visitor_id'].unique()
И удаляем этих пользователей из таблицы orders:
orders = orders.query('visitor_id not in @double_users')



