2017-05-19 1 views
6

Pour l'ensemble de données test, mon objectif est de connaître le nombre d'utilisateurs uniques reportés d'une période à l'autre, période par période.Calcul de la rétention simple dans R

> test 
    user_id period 
1  1  1 
2  5  1 
3  1  1 
4  3  1 
5  4  1 
6  2  2 
7  3  2 
8  2  2 
9  3  2 
10  1  2 
11  5  3 
12  5  3 
13  2  3 
14  1  3 
15  4  3 
16  5  4 
17  5  4 
18  5  4 
19  4  4 
20  3  4 

Par exemple, dans la première période, il y avait quatre utilisateurs uniques (1, 3, 4 et 5), dont deux ont été actifs dans la deuxième période. Par conséquent, le taux de rétention serait de 0,5. Au cours de la deuxième période, il y avait trois utilisateurs uniques, dont deux étaient actifs durant la troisième période, et le taux de rétention était de 0,666, et ainsi de suite. Comment trouver le pourcentage d'utilisateurs uniques actifs dans la période suivante? Toute suggestion serait appréciée.

La sortie serait la suivante:

> output 
    period retention 
1  1  NA 
2  2  0.500 
3  3  0.666 
4  4  0.500 

Les données test:

> dput(test) 
structure(list(user_id = c(1, 5, 1, 3, 4, 2, 3, 2, 3, 1, 5, 5, 
2, 1, 4, 5, 5, 5, 4, 3), period = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 
2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4)), .Names = c("user_id", "period" 
), row.names = c(NA, -20L), class = "data.frame") 

Répondre

0

Ce n'est pas si élégant mais il semble fonctionner. En supposant que df est la trame de données:

# make a list to hold unique IDS by 
uniques = list() 
for(i in 1:max(df$period)){ 
    uniques[[i]] = unique(df$user_id[df$period == i]) 
} 

# hold the retention rates 
retentions = rep(NA, times = max(df$period)) 

for(j in 2:max(df$period)){ 
    retentions[j] = mean(uniques[[j-1]] %in% uniques[[j]]) 
} 

Fondamentalement, le% en% crée une logique de savoir si oui ou non chaque élément du premier argument est dans le second. Prendre un moyen nous donne la proportion.

4

Que pensez-vous de cela? Commencez par diviser les utilisateurs par période, puis écrivez une fonction qui calcule la proportion de report entre deux périodes, puis faites-la passer en boucle dans la liste de division avec mapply.

splt <- split(test$user_id, test$period) 

carryover <- function(x, y) { 
    length(unique(intersect(x, y)))/length(unique(x)) 
} 
mapply(carryover, splt[1:(length(splt) - 1)], splt[2:length(splt)]) 

     1   2   3 
0.5000000 0.6666667 0.5000000 
3

Voici une tentative en utilisant dplyr, mais il utilise également une syntaxe standard dans le summarise:

test %>% 
group_by(period) %>% 
summarise(retention=length(intersect(user_id,test$user_id[test$period==(period+1)]))/n_distinct(user_id)) %>% 
mutate(retention=lag(retention)) 

Ce retour:

period retention 
    <dbl>  <dbl> 
1  1  NA 
2  2 0.5000000 
3  3 0.6666667 
4  4 0.5000000 
+0

Ne serait-il mieux si vous calculez longueur des user_ids uniques? Je pense que si un utilisateur apparaît deux fois dans une période, il devrait toujours compter comme un utilisateur de retour. –

+0

@giac_man Par défaut, 'intersect' supprime tous les doublons, il n'est donc pas nécessaire d'ajouter' unique' car l'opération y est déjà incluse. – Lamia

+0

Ah, je vois. Merci –