#python #pandas
#python #pandas
Вопрос:
Я пытаюсь подсчитать количество электронных писем, которые каждый пользователь открывает подряд. У меня есть данные, отсортированные по адресу электронной почты и дате, и я могу подсчитать # открыто в строке, но я не могу понять, как заставить его сбросить значение 0 при появлении нового адреса электронной почты.
Это то, что у меня есть до сих пор. При этом учитывается число открытых строк, но оно не сбрасывается на 0 при появлении нового адреса электронной почты.
in_a_row = []
count = 0
for row in merge['Opened?']:
if row == 1:
count = 1
in_a_row.append(count)
elif row == 0:
count = 0
in_a_row.append(count)
merged['in_a_row'] = in_a_row
Вот как это выглядит в настоящее время
Index email_address sent_date sent_rank Opened? in_a_row
0 email_A@gmail.com 5/15/2018 1 1 1
1 email_A@gmail.com 5/23/2018 2 0 0
2 email_A@gmail.com 5/23/2018 3 1 1
3 email_B@gmail.com 5/26/2018 1 1 2
4 email_B@gmail.com 5/27/2018 2 1 3
5 email_B@gmail.com 8/2/2018 3 0 0
6 email_B@gmail.com 8/3/2018 4 1 1
7 email_B@gmail.com 12/12/2018 5 1 2
8 email_C@gmail.com 12/12/2018 1 1 3
9 email_C@gmail.com 2/6/2019 2 0 0
10 email_C@gmail.com 2/12/2019 3 1 1
Вот как это должно выглядеть
Index email_address sent_date sent_rank Opened? in_a_row
0 email_A@gmail.com 5/15/2018 1 1 1
1 email_A@gmail.com 5/23/2018 2 0 0
2 email_A@gmail.com 5/23/2018 3 1 1
3 email_B@gmail.com 5/26/2018 1 1 1
4 email_B@gmail.com 5/27/2018 2 1 2
5 email_B@gmail.com 8/2/2018 3 0 0
6 email_B@gmail.com 8/3/2018 4 1 1
7 email_B@gmail.com 12/12/2018 5 1 2
8 email_C@gmail.com 12/12/2018 1 1 1
9 email_C@gmail.com 2/6/2019 2 0 0
10 email_C@gmail.com 2/12/2019 3 1 1
Комментарии:
1. Я не понимаю логику первого изменения с 1 на 0
in_a_row
. Разве это не новый адрес?2. При
Opened?
переходе от 1 к 0 одновременноemail_address
счетчик также сбрасывается?3. Другой вопрос, почему все адреса электронной почты начинают подсчет с
0
, но первый адрес электронной почты начинается с1
?4. Похоже, в таблицах были некоторые опечатки, извините за это, их следует исправить сейчас. При открытии? = 0, это означает, что электронное письмо было закрыто при открытии? = 1 это означает, что оно было открыто. Счетчик всегда должен сбрасываться на 0, когда электронное письмо не открывается, но он также должен сбрасываться на 0, когда появляется новый адрес электронной почты.
5.
email_address
всегда ли они группируются таким образом? т.Е. Можно ли увидеть email_A@gmail.com после email_C@gmail.com в строке 11 или 12?
Ответ №1:
Попробуйте это groupby.transform
с помощью лямбда-выражения с использованием .ne
( !=
), .shift
, .cumsum
и .add
:
g = df.groupby('email_address')
df['in_a_row'] = g['Opened?'].transform(lambda x: x * (x.groupby((x.ne(x.shift())).cumsum()).cumcount().add(x)))
Примечание: я думаю, что в вашем желаемом выводе все еще могут быть некоторые опечатки. например, idx 8
и 9
входные и выходные данные имеют разные значения для Opened?
[вывод]
Index email_address sent_date sent_rank Opened? in_a_row
0 0 email_A@gmail.com 5/15/2018 1 1 1
1 1 email_A@gmail.com 5/23/2018 2 0 0
2 2 email_A@gmail.com 5/23/2018 3 1 1
3 3 email_B@gmail.com 5/26/2018 1 1 1
4 4 email_B@gmail.com 5/27/2018 2 1 2
5 5 email_B@gmail.com 8/2/2018 3 0 0
6 6 email_B@gmail.com 8/3/2018 4 1 1
7 7 email_B@gmail.com 12/12/2018 5 1 2
8 8 email_C@gmail.com 12/12/2018 1 1 1
9 9 email_C@gmail.com 2/6/2019 2 0 0
10 10 email_C@gmail.com 2/12/2019 3 1 1
Комментарии:
1. Это действительно близко. Это работает для выборочных данных, но когда я применил его к большему набору данных, похоже, что есть исключения, которые не учитывались в данных выборки. Я обновил индекс 5, поэтому есть пример, когда он не работает. Теперь это открылось? при индексе 5 равно 0, in_a_row при индексе 6 должно быть 0, но вместо этого 2. Кроме того, вы были правы насчет опечаток, спасибо, что указали на них.
2. Спасибо, что указали на это @Tim344. посмотрим на это
3. @Tim344 обновил мой ответ, если вы хотите повторить это снова?