pandas: найти первое вхождение даты для каждого пользователя
Есть таблица с несколькими столбцами, в том числе user_id и date. Одному пользователю может принадлежать несколько значений дат. Необходимо найти первое вхождение даты и присвоить ему какой-либо признак (напротив соответствующей строки добавить в новый столбец значение 'first'). Предполагаю что нужно пройтись циклом по таблице, для каждого user_id и date проверить дату, методом first или min и для первой даты сделать запись в новом столбце. Помогите пожалуйста.
| user_id | date |
|---|---|
| 1110 | 2020-02-16 |
| 1110 | 2020-02-15 |
| 9999 | 2020-02-16 |
| 1110 | 2020-01-10 |
| 9999 | 2020-03-16 |
в выводе ожидается:
| user_id | date | new_column |
|---|---|---|
| 1110 | 2020-02-16 | NaN |
| 1110 | 2020-02-15 | NaN |
| 9999 | 2020-02-16 | first |
| 1110 | 2020-01-10 | first |
| 9999 | 2020-03-16 | NaN |
Update: Не учел еще один признак в другом столбце, с Вашего позволения усложню задачу. Необходимо найти первое вхождение даты для конкретного iser_id c признаком True и присвоить ему в новом столбце значение 6. Остальные строки в новом столбце заполнить нулями.
| user_id | date | payer |
|---|---|---|
| 1110 | 2020-01-24 | True |
| 1110 | 2020-01-17 | True |
| 9999 | 2020-02-16 | False |
| 1110 | 2020-01-10 | False |
| 9999 | 2020-02-23 | True |
Вывод должен быть следующим:
| user_id | date | payer | new_column |
|---|---|---|---|
| 1110 | 2020-01-24 | True | 0 |
| 1110 | 2020-01-17 | True | 6 |
| 9999 | 2020-02-16 | False | 0 |
| 1110 | 2020-01-10 | False | 0 |
| 9999 | 2020-02-23 | True | 6 |
Глобальный смысл задачи: клиент на первой неделе пользуется триал-версией продукта, на второй неделе у него начинается платная подписка, за привлечение такого клиента бизнес единоразово платит 6 рублей, эту информацию и нужно занести в таблицу. За последующие периоды никаких выплат за клиента нет. Спасибо.
Ответы (4 шт):
Можно попробовать сделать так:
df.loc[df.sort_values("date").
groupby("user_id").
apply(lambda x: x.index[0]), "mark"] = "first"
получится df:
user_id date mark
0 1110 2020-02-16 NaN
1 1110 2020-02-15 NaN
2 9999 2020-02-16 first
3 1110 2020-01-10 first
4 9999 2020-03-16 NaN
Немного длинный, но работает.
df.loc[df.set_index(['name', 'date']).index.isin(df.groupby('name')['date'].min().reset_index().\
set_index(['name', 'date']).index), 'new_col'] = 'first'
>>>
name date new_col
0 1110 2020-02-16 NaN
1 1110 2020-02-15 NaN
2 9999 2020-02-16 first
3 1110 2020-01-10 first
4 9999 2020-03-16 NaN
чуть покороче:
df.loc[df.groupby('user_id')['date'].idxmin(),'new_col'] = 'first'
и желательно сразу приводить date к типу datetime
У меня получилось с помощу sort_values и drop_duplicates
df.sort_values(by=['id']).drop_duplicates(subset='id', keep='first')