1
votes

Compteur itératif basé sur plusieurs variables

J'essaie de créer un compteur pour suivre le nombre d'échecs et de succès concernant plusieurs utilisateurs différents. J'ai un dataframe avec des codes utilisateurs qui se répètent (s'il y a plus d'événements sur les mêmes utilisateurs) et un horodatage pour suivre la variable de temps. J'aimerais ajouter deux colonnes (# de succès, # d'échecs) qui cumulent le résultat des événements précédents.

Exemple de données:

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]
    }
)

J'ai essayé avec quelques boucles en R mais j'ai peur de manquer quelque chose, peut-être y a-t-il une meilleure façon de faire cela en Python?

Le résultat souhaité serait quelque chose comme ceci:

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']
    }
)


0 commentaires

3 Réponses :


2
votes

Utilisez la série . eq pour créer un masque booléen, puis utilisez Series.groupby , sur ce masque et transformez la série groupée en utilisant .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

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


0 commentaires

2
votes
    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

0 commentaires

1
votes

Utilisons get_dummies:

    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

Output:

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_'))

Ce que j'aime dans l'utilisation de str.get_dummies est que cela traitera plus que simplement «oui» et «non», insérons un nouveau statut «peut-être»:

    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

Résultat:

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


2 commentaires

Bonne utilisation de get_dummies .


Génial, toutes les réponses étaient appropriées mais c'est vraiment une belle, merci.