Итерационный счетчик на основе нескольких переменных - PullRequest
1 голос
/ 17 июня 2020

Я пытаюсь создать счетчик, чтобы отслеживать количество неудач и успехов для нескольких разных пользователей. У меня есть фрейм данных с пользовательскими кодами, которые повторяются (если есть больше событий для одних и тех же пользователей), и временная метка для отслеживания временной переменной. Я хотел бы добавить два столбца (количество успехов, количество сбоев), которые суммируют результат предыдущих событий.

Пример данных:

data=pd.DataFrame(
    {
        'user_id': [2,2,3,2,4,5,3,3,6,6,6,7],
        'timestamp': [1567641600,1567691600,1567741600,1567941600, 1567981600, 1567991600,1568391600,1568541600,1568741600,1568941600,1568981600,1568988600],
        'status': ['yes','no','yes','no', 'yes', 'yes','yes','no','no','yes','no','yes']
    }
)

Я пробовал с некоторыми циклами в R но боюсь, я чего-то упускаю, может быть, есть лучший способ сделать это в Python?

Желаемый результат будет примерно таким:

data=pd.DataFrame(
    {
        'user_id': [2,2,3,2,4,5,3,3,6,6,6,7],
        'timestamp': [1567641600,1567691600,1567741600,1567941600, 1567981600, 1567991600,1568391600,1568541600,1568741600,1568941600,1568981600,1568988600],
        'status': ['yes','no','yes','no', 'yes', 'yes','yes','no','no','yes','no','yes'],
        'number_yes':[1,1,1,1,1,1,2,2,0,1,1,1],
        'number_no':[0,1,0,2,0,0,0,1,1,1,2,0]
    }
)

Ответы [ 3 ]

2 голосов
/ 17 июня 2020
data['number_yes'] = data.groupby('user_id').status.transform(lambda x: (x == 'yes').cumsum())
data['number_no'] = data.groupby('user_id').status.transform(lambda x: (x == 'no').cumsum())

Результат:

    user_id   timestamp status  number_yes  number_no
0         2  1567641600    yes           1          0
1         2  1567691600     no           1          1
2         3  1567741600    yes           1          0
3         2  1567941600     no           1          2
4         4  1567981600    yes           1          0
5         5  1567991600    yes           1          0
6         3  1568391600    yes           2          0
7         3  1568541600     no           2          1
8         6  1568741600     no           0          1
9         6  1568941600    yes           1          1
10        6  1568981600     no           1          2
11        7  1568988600    yes           1          0
2 голосов
/ 17 июня 2020

Используйте, Series.eq, чтобы создать логическую маску, затем используйте Series.groupby на этой маске и преобразуйте сгруппированный ряд, используя .cumsum :

m = data['status'].eq('yes')
data = data.assign(
    number_yes=m.groupby(data['user_id']).cumsum(),
    number_no=(~m).groupby(data['user_id']).cumsum()
)

# print(data)
    user_id   timestamp status  number_yes  number_no
0         2  1567641600    yes         1.0        0.0
1         2  1567691600     no         1.0        1.0
2         3  1567741600    yes         1.0        0.0
3         2  1567941600     no         1.0        2.0
4         4  1567981600    yes         1.0        0.0
5         5  1567991600    yes         1.0        0.0
6         3  1568391600    yes         2.0        0.0
7         3  1568541600     no         2.0        1.0
8         6  1568741600     no         0.0        1.0
9         6  1568941600    yes         1.0        1.0
10        6  1568981600     no         1.0        2.0
11        7  1568988600    yes         1.0        0.0
1 голос
/ 17 июня 2020

Давайте использовать get_dummies:

data.join(data['status'].str.get_dummies()
                        .groupby(data['user_id']).cumsum()
                        .add_prefix('Number_'))

Вывод:

    user_id   timestamp status  Number_no  Number_yes
0         2  1567641600    yes          0           1
1         2  1567691600     no          1           1
2         3  1567741600    yes          0           1
3         2  1567941600     no          2           1
4         4  1567981600    yes          0           1
5         5  1567991600    yes          0           1
6         3  1568391600    yes          0           2
7         3  1568541600     no          1           2
8         6  1568741600     no          1           0
9         6  1568941600    yes          1           1
10        6  1568981600     no          2           1
11        7  1568988600    yes          0           1

Что мне нравится в использовании str.get_dummies, так это то, что он будет обрабатывать больше, чем просто «да» и ' нет ', давайте вставим новый статус' возможно ':

data=pd.DataFrame(
    {
        'user_id': [2,2,3,2,4,5,3,3,6,6,6,7],
        'timestamp': [1567641600,1567691600,1567741600,1567941600, 1567981600, 1567991600,1568391600,1568541600,1568741600,1568941600,1568981600,1568988600],
        'status': ['yes','no','yes','no', 'maybe', 'yes','yes','no','maybe','yes','no','yes']
    })

data.join(data['status'].str.get_dummies()
                        .groupby(data['user_id']).cumsum()
                        .add_prefix('Number_'))

Вывод:

    user_id   timestamp status  Number_maybe  Number_no  Number_yes
0         2  1567641600    yes             0          0           1
1         2  1567691600     no             0          1           1
2         3  1567741600    yes             0          0           1
3         2  1567941600     no             0          2           1
4         4  1567981600  maybe             1          0           0
5         5  1567991600    yes             0          0           1
6         3  1568391600    yes             0          0           2
7         3  1568541600     no             0          1           2
8         6  1568741600  maybe             1          0           0
9         6  1568941600    yes             1          0           1
10        6  1568981600     no             1          1           1
11        7  1568988600    yes             0          0           1
...