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']
}
)
3 Réponses :
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()
)
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
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_'))
Bonne utilisation de get_dummies .
Génial, toutes les réponses étaient appropriées mais c'est vraiment une belle, merci.