figure : Une vie de babouine1

Introduction

Si les cartes de fidélité ont moins d’attrait c’est qu’elles se sont multipliées, se concurrencent par le multihoming, et ont du souvent reconsidérer leur plan de gratification à la baisse, réduisant la valeur des points où relevant les seuils de statut, elles n’en restent pas moins le moyen principal pour les marques de suivre la consommation de leurs clients et demeurent un élément clé du système de gestion de la clientèle (CRM). Sans adhésion, sans numéro, il n’y a pas de connaissance client.

Les distributeurs, les compagnies aériennes, les hotels, toutes les industries de services qui délivrent des prestations répétées à la guise du client, prétendent à modifier les achats subséquents en récompensant l’achat actuel. Ceci se traduit par une distribution de points à chaque achat, selon des barème plus ou mois complexes, mais dont on suppose qu’ils peuvent affecter l’achat suivant soit en le précipitant, soit en accroissant sa valeur monétaire.

La question de leur efficacité est posée depuis longtemps, elle a été un de nos sujets de recherche (Meyer-Waarden and Benavent (2006), Meyer-Waarden and Benavent (2009)) . (un brief de la litt est nécessaire - à compléter)

L’étude qui fait l’objet de ce carnet de note, s’appuie sur un cas caractéristique, et vise à présenter des analyses comportementale de la relation par l’analyse des transactions. Autrement dit la liste des actes d’achat au cours du temps d’une cohorte de consommateursdont une possède une description sommaire.

Elle suit de près une publication encore plus ancienne qui portait sur un cas similaire, et avec une échelle de donnée équivalente BENAVENT and CRIÉ (1998) . On va y retrouver des éléments analogues qui font de cette étude une réplication positive qui confirme la généralité des résultats obtenus il y a bien longtemps.

Cette étude reste cependant méthodologique et pédagogique et vise à détailler des analyses standards de ce type de structure de données, en particulier l’application de modèle de cox pour analyser la durée de vie des porteurs de carte de fidélité, un modèle linaire hiérarchique pour tester l’effet des récompenses acquises et de différents outils graphiques.

Préparation des données

Les données sont relationnelles, à un niveau minimal. On dispose de 4 fichiers reliés par leur index :

Même simple, cette structure conduit à une gymnastique des données, où pour produire les tableaux à analyser, il va falloir filtrer, merger, agréger. Dans cette esprit on consultera avec profit ce chapitre d’un excellent ouvrage et on en profitera pour se mettre sérieusement à dplyr

On retiendra de cette structure dans une représentation simple le schéma suivant. Elle se contruit avec trois éléments

Initialisation

Voici la liste des packages néçessaires pour nos analyses.

knitr::opts_chunk$set(echo = TRUE, include = TRUE, message=FALSE,Warning=FALSE)
library(tidyverse) #la boite à outils qui monte qui monte, indipensable pour les graphique , indiemnsable pour reconstruire les données
library(reshape2) #indispensable pour ggplot
library(readr)
library(Rcmdr) # si on a besoin d'interactivité
library(survival) #le coeur de notre analyse
library(survminer) #un outil pour bien représen,ter la survie ou le rique
## Warning: package 'survminer' was built under R version 3.5.3
library(lubridate) #bien utile pour manipuler les dates
library(gglorenz) #analyse des concetration autrement la verification des 20:80
library(ineq) # un compment aux analyse de concentratrion
library(jtools)
library(lme4) # pour des regression complexe
library(nlme)  # pour des regression complexe mais aussi d'autres méthodes
library(effects)
library(ape)  #ape est le pacckahe de la phylogénie mais fournit des ressources essentielle pour mieux pratiquer le clusting
library(gridExtra) #question de mettre des graphique dans un meme espace
library(viridis) #pour les couleurs
library(knitr) 
library(kableExtra) #affichage des tableaux
library(stargazer) #pour comparer les modèles de regression et de survie

#pour arranger les figures en une


#lecture des fichiers
Customer <- read.csv("~/AtelierR/botanic/Custom.csv", encoding="UTF-8")

#passage en caisse (ticket)
Purchase <- read.csv("~/AtelierR/botanic/Purchase.csv")

Commencons par représenter l’ensemble des données et donc la distribution dans le temps des achats , ou passage en caisse réalisés, par une cohorte d’adhérents à la carte de fidélité.

Compte-tenu de la nature historique des données on utilisera largement le package lubridate pour manipuler les dates, les temps et les durées.

Description de la série

Pour obtenir un sens plus concrêt des données en voici une représentation simple : le nombre de transactions journalières effectuées par les clients qui ont adopté la carte en 2010 au cours des quatre années suivantes. On y observe : * une saisonnalité prononcée avec un pic au printemps (quand le jardin se prépare) et en décembre quand il faut trouver des idées de cadeaux. * une baisse du nombre absolu des achats qui traduit l’attrition, les membres du programme disparaissent, soit qu’ils n’utilisent plus la carte pour bénéficier des avantages (les points) soit qu’ils ne sont plus clients de l’enseigne.

Purchase$Date<-as.POSIXct(Purchase$Date) #un format qu'aime lubridate
g<-Purchase %>% 
  ggplot(aes(Date)) + 
  geom_freqpoly(binwidth = 86400) + labs(title = "Nombre d'achats par jour",caption = "Archives personnelles",x="temps",y="nb de passage en caisse") 
g

# le choix du binwidth est justifié par ce que  86400 seconds = 1 day

Pour mieux représenter la saisonnalité, identifions le nombre moyen d’achats par jour de la semaine, par jour du mois, et par mois de l’année. On y retrouve un fort rythme saisonnier (avril/mai; décembre), un rythme hebdomadaire qui concentre les ventes le we, et dans une importance moins nette des achats un peu plus denses en début de mois mais c’est à prouver. Les achats se font vers 11h ou 17h.

g0<-Purchase %>% 
  mutate(heures = hour(Date)) %>% 
  ggplot(aes(x = heures)) + geom_bar(fill="orange")+theme_minimal()

g1<-Purchase %>% 
  mutate(wday = wday(Date, label = TRUE)) %>% 
  ggplot(aes(x = wday)) + geom_bar(fill="orange")+theme_minimal()


g2<-Purchase %>% 
  mutate(mday = mday(Date)) %>% 
  ggplot(aes(x = mday)) +  geom_bar(fill="coral3")+theme_minimal()

g3<-Purchase %>% 
  mutate(Month = month(Date, label = TRUE)) %>% 
  ggplot(aes(x = Month)) +geom_bar(fill="brown")+theme_minimal()

grid.arrange(g0,g1,g2,g3,nrow=2)

Analyse de l’attrition

C’est un enjeu essentiel que de comprendre l’attrition des clients. Pour l’apprécier, on emploie les ressource de l’analyse de survie. Comment modéliser les chance qu’un souscripteur à la carte soit toujours client au bout d’une durée t ?

Les durées de vie des clients

Examinons les durées écoulées entre l’adhésion et le dernier achat. On trouve des pics annuels qui correspondent vraisembablement aux dates de renouvellement, ou plutôt de non-renouvelement de la carte. Ils sont à peu près annuel (365 jours). On note naturellement le pic initial correspondant aux achats uniques, ceux qui ont été produit au moment de l’adhésion et n’ont pas fait d’autres achats. Soit que les clients aient disparus, soit qu’ils n’utilisent pas leur carte.

On calcule séparemment sur la base du fichier des achats la plus faible et la plus forte des valeurs ( le premier et le dernier achat) qu’on matche en un fichier donc l’index est l’individu. La durée de vie est calculée en faisant la différente des dates de premier et de dernier achat. Il n’y a plus qu’à examiner l’histogramme des durées de vie ( exprimée en jour).

c1<-group_by(Purchase, idclient) %>% summarise(mind = min(Date))
c2<-group_by(Purchase, idclient) %>% summarise(maxd = max(Date))
c1<-cbind(c1,c2[2])

c1<-c1 %>% mutate(duration=as_date(maxd)-as_date(mind))
c1<-as.data.frame(c1)
g<-ggplot(c1,aes(x = duration))+geom_histogram(binwidth =5)+xlim(1,1600)+ annotate("text", x = 500, y = 100, label ="la durée 0 jour n'est pas représentée \n la fréquence de cette modalité est de plus de 800")+theme_minimal()
g
## Warning: Removed 761 rows containing non-finite values (stat_bin).
## Warning: Removed 2 rows containing missing values (geom_bar).

Définition de la variable de censure

Ces données se prêtent parfaitement à des analyses de survie, il faut cependant indiquer si ces durées sont censurée ou pas. Autrement dit quelque soit leur durée, si l’evenement a été observé ou pas. Cet évenement est la disparition du client qui ne refaira plus d’autres achats. S’il n’est pas observé, il est probable que la durée d’échat s’étendra audelà de la date d’observation, mais nous ne le savons pas. La cience des modèles de survie c’est de prendre en compte ce facteur pour donner des estimations qui ne soit pas biaisées. On comprend que si on prend les durée telles quelles, on en minise la durée moyenne.

(insérer un graphique des durées)

La censure est donc la variable qui signale si, à la date de l’étude, l’événement s’est produit ou ne s’est pas encore produit, implicant que la durée mesurée est la durée minimale et qu’on en connaît pas encore la valeur exacte. On peut s’appuyer sur deux méthodes :

  • la première prend en compte la date de non renouvellement de la carte de fidélité

  • la seconde s’appuie sur l’analyse des achat et un critère simple qui est celui d’un critère de décision discrimant les derniers achats marquant l’arrêt définitif, de ceux qui sont simplement les derniers achats observés.

c’est la seconde méthode que l’on choisit. Le critère de décision va s’appuyer sur le calcul d’une durée écoulée entre le dernier achat observé et la date de l’étude pour tenir compte de la variabilité individuelle. Si cette durée est significative plus grande que la durée inter-achat, on en déduit que la probabilité que le client a disparu est élevée.

Mais auparavant représentons ces durées inter-achats pour ceux qui ont réalisé plus de deux achats. On retrouve une distribution centrée sur une trentaine de jour. Le rythme serait ainsi plutôt mensuel.

Purchase$n<-1
c2<-aggregate(n~idclient,data=Purchase,sum )
end <- as.POSIXct('2014-1-1') #fixer la date d'étude
#calculer la duree interachat durée-totale/nombre d'achats et la durée ecoulée depuis le dernier achat - ne garder que ceux qui ont fait deux achats
c1<-cbind(c1,c2[2])  %>% mutate(fq=duration/n) %>% mutate(last= end-maxd ) %>% filter(n>1)
#initialiser la censure à 1 
c1$censure<-1
#donner la valeur de 2 si la duree ecoulee est superieure à 2x la duree inter achat.
c1$censure[c1$last>2*c1$fq]<-2
c1$censure<-as.factor(c1$censure)
#afficher la distribution des durées interachats
ggplot(c1,aes(x=fq,group=censure))+geom_density(binwidth = 10)+xlim(0,400)+ labs(x = "durée inter-achat (en j)")+theme_minimal()+facet_grid(censure~.)
## Warning: Ignoring unknown parameters: binwidth
## Warning: Removed 21 rows containing non-finite values (stat_density).

Une première approche par la méthode de Kaplan-Meyer

Elle est univarié, elle est actuaire, elle représente les données sans explication sauf à comparer des groupes distincts, elle donne l’allure du phénomène. C’est en 1958 qu’elle a été inventée, en voici le texte fondamental, et un commentaire collector de 1983.

On y relève deux points d’inflexion qui correspondent au rythme annuel du renouvellement (la carte est payante pour une somme modique et valable un an). Au premier point, à moins de 400 jours c’est la moitié des adhérents qui disparaissent. Au bout de 3 ans il en reste un peu plus de 20%.

c1<-merge(Customer,c1, by.x="idclient",by.y="idclient", all.x=FALSE, all.y=FALSE, sort=TRUE)

#kaplanmeier
c1$SurvObj <- with(c1, Surv(duration, censure == 2))
km <- survfit(SurvObj ~ 1, data = c1, conf.type = "log-log")
km
## Call: survfit(formula = SurvObj ~ 1, data = c1, conf.type = "log-log")
## 
##       n  events  median 0.95LCL 0.95UCL 
##    4235    3161     431     419     452
plot(km)

Modèle de Cox

Le génie du modèle de Cox est de modéliser le risque en deux composantes. La première est la forme générale du risque qui prend l’allure d’un vecteur numérique du temps, sans aucune spcéfication de loi, un modèle purement paramètrique, qui est pôndéré par une seconde composante, une fonction linéaire des caractériques de l’objet dont on souhaite mesuré la survie. On consultera Cox pour le texte séminal et pour la mise en oeuvre sous.

C’est au fond un modèle de régression ou le terme constant est remplacée par une courbe de risque, sa propriété est de conserver au cours du temps les rapports de risque. Sa formalisation est la suivante :

\[h_{it}=h_{0,t}\exp^{X_{i}\beta}\]

On utilise le package survmining et pour aller plus loin on consultera avec profits ce lien et le suivant.

Dans la séquence suivante on spécifie le modèle, puis avec la fonction cox.zph on evalue la proportionnalité des risques. Les deux dernières lignes sont destinées à représenter les courbes de survie et de risque cumulé pour une variable qui attire notre intention. C’est une reprensation stratifiée

#cox
res.cox1 <- coxph(SurvObj ~  C_sms + C_mail + C_email+Habitat+segment, data =  c1)
res.cox1
## Call:
## coxph(formula = SurvObj ~ C_sms + C_mail + C_email + Habitat + 
##     segment, data = c1)
## 
##                          coef exp(coef) se(coef)      z        p
## C_sms                 0.06091   1.06281  0.05237  1.163 0.244804
## C_mail               -0.46143   0.63038  0.06773 -6.813 9.58e-12
## C_email              -0.05222   0.94912  0.04539 -1.150 0.249963
## HabitatAppartement   -0.05063   0.95063  0.07319 -0.692 0.489057
## Habitatmaison        -0.07063   0.93181  0.06425 -1.099 0.271690
## segmentBON-DIVERSITE -0.24608   0.78186  0.21633 -1.138 0.255310
## segmentINACTIF        3.01491  20.38727  0.15322 19.676  < 2e-16
## segmentJARDIN        -0.02796   0.97243  0.16871 -0.166 0.868365
## segmentJARDIN MAISON -0.12517   0.88235  0.19978 -0.627 0.530950
## segmentNON JARDIN     0.58832   1.80097  0.16814  3.499 0.000467
## segmentTOP-DIVERSITE -1.19636   0.30229  0.47163 -2.537 0.011192
## 
## Likelihood ratio test=3900  on 11 df, p=< 2.2e-16
## n= 4235, number of events= 3161
(res.zph1 <- cox.zph(res.cox1))
##                           rho    chisq        p
## C_sms                -0.00574 1.06e-01 7.45e-01
## C_mail                0.02151 1.45e+00 2.29e-01
## C_email              -0.00428 5.85e-02 8.09e-01
## HabitatAppartement    0.00684 1.46e-01 7.02e-01
## Habitatmaison         0.00448 6.35e-02 8.01e-01
## segmentBON-DIVERSITE  0.01250 4.92e-01 4.83e-01
## segmentINACTIF       -0.09271 2.53e+01 4.87e-07
## segmentJARDIN         0.00679 1.46e-01 7.03e-01
## segmentJARDIN MAISON  0.00365 4.21e-02 8.37e-01
## segmentNON JARDIN     0.00110 3.85e-03 9.51e-01
## segmentTOP-DIVERSITE  0.00483 7.37e-02 7.86e-01
## GLOBAL                     NA 2.13e+02 1.18e-39
#plot(res.zph1)
c1$duration2<-as.numeric(c1$duration)
fit <- survfit(Surv(duration, censure==2) ~ C_mail, data = c1)
library(survminer)
ggsurvplot(fit, data = c1,conf.int = TRUE)

ggsurvplot(fit, data = c1, fun = "cumhaz",conf.int = TRUE)

Une variable semble faire la différence : le fait que le souscripteur aie acceptué de donner son addresse terrestre. En acceptant de s’identifier il signale son comportement futur : plus fidèle. On s’apercoit memem quand on examine le diagramme des taux de risque cumulé qu’il échappe à l’exode de la quatrième année.

Ce modèle simple fait de la survie des clients en tant que client fidélisé le résultat de caractéristiques intrinsèque à l’individu. L’exemple des adresse de contact révèle que la fidélité se rélève par le consementement du client à être recontacter. S’il laisse son adresse mail, terrestre ou mobile, c’est qu’il est dans une disposition favorable et la preuve vient de ce que systématique le taux de risque est plus faible pour ceux qui ont donnés leur coordonnées au moement de l’adhésion. Les actes d’achats sont observés de manière postérieure et sont ainsi indépendant de l’état antérieur. La causalité est établie mais sa nature est interprêtée. donner son adresse c’est traduire une attitude persistante.

Les tests de non-proportionnalité sont importants car il permettent de justifier pour les variables introduite dans la partie deterministe du modèle l’idée un effet constant, indépendant du temps. La proportionnalité des taux de risque est fixée dans la nature même du modèle.

Considérons un modèle très simple réduit à une variable binaire : on possède le mail qu’il a donné ou on a pas l’information codé 1 ou 0.Examinons le rapport des risques pour les deux modalités. Le rato des risque est égal à une constante dont la valeur dépend d’un paramètre. Les rapport de risques sont constant.

\[\frac{h_{0,t}\exp^{1\beta}}{h_{0,t}\exp^{0\beta}}= \exp^{\beta}\]

Le rapport des probabilités de survie reste constant à travers le temps. Dans notre cas ces proportionnalités sont testées par le test rho et par des graphiques. Ces derniers traduisent une parfaite parrallélisme.

Des variables qui varient dans le temps

Dans notre cas, d’autres variables que celles qui décrivent les individus sont disponibles, en particulier la connaissance des dates d’achat au cours de la vie du client. Il est parfaitement légitime de penser que ces expériences d’achats soient susceptibles d’affecter la continuence des achats ( note de bas de page sur la continuance). Chaque acte d’achat est l’occasion d’éprouver la marque et ses produits, si l’expérience est possitive on s’attend à ce que le client soit incité à répéter et à prolonger sa vie de client. les expériences négatives risque de réduire la survie.

Les actes d’achats sont ainsi des variables qui varient dans le temps et ont un effet présumés qui se distibuent dans le temps en fonction de leur apparition.

le modèle est donc

sur un plan pratique on va utiliser des ressources de tmerge qui est une fonction difficile à utiliser. Elle crée les variables dont nous avons besoin : des départs, des fins, des censures, des evenements, pour présenter les données sous une forme qui enregistre les individus et les séquences marqué par un début de vie, des évenements, et une fin de vie ou une censure .

i tstart tstop evenement actions censure 1 0 50 1
1 51 102 1
1 103 116 1 1 2 2

pour structurer les données on emploie la fonction tmerge qui est délicate et complexe à mettre en oeuvres, mais ensuite très éfficace pour construire le fichier de données nécessaires. Ce document est utile pour une première approche et on consultera la vignette, si necessaire on regardera cette présentation (https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&cad=rja&uact=8&ved=2ahUKEwiW58Pc5IbhAhWInxQKHVwACNoQFjADegQIBBAC&url=https%3A%2F%2Fww2.amstat.org%2Fmeetings%2Fsdss%2F2018%2Fonlineprogram%2FViewPresentation.cfm%3Ffile%3D304494.pdf&usg=AOvVaw0RCQfeZHAVih5vsiP8Fszl)

On estime le modèle avec la meme procedure ci-dessus, excepté qu’on introduit dans le modèle deux nouvelles variables : le fait qu’un achat ( un passage caisse, une visite en magasin) soit réalisé, et le cumul des achats réalisés jusqu’au temps t. analyser les résultats : on s’apercoit qu’aussi bien le cumul des achats que l’évenement achat tendent à accroitre la survie ( expliquer le signe négatif)

#preparation fichier

c1_f<-c1 %>% filter(duration>0)

c1_pf<-merge(c1_f,Purchase[,2:6],by="idclient", all=FALSE)

c1_pf$time<-round(as.POSIXct(c1_pf$Date)-as.POSIXct('2010-1-1'),0)

newdata <- tmerge(c1_f, c1_f, id = idclient, action = event(duration,censure))

newdata2<- tmerge(newdata,c1_pf, id = idclient, purchase = event(time, Montant), cumul=cumevent(time, Montant))

fit <- coxph(Surv(tstart, tstop, action==2) ~ C_mail +status+purchase, data=newdata2)
fit2 <- coxph(Surv(tstart, tstop, action==2) ~ C_mail +status+purchase+cumul, data=newdata2)


stargazer(fit,fit2,type = "text")
## 
## ================================================================
##                                  Dependent variable:            
##                      -------------------------------------------
##                                        tstart                   
##                               (1)                   (2)         
## ----------------------------------------------------------------
## C_mail                     -0.314***              -0.105        
##                             (0.067)               (0.067)       
##                                                                 
## statusVIP                  -1.928***             -0.264**       
##                             (0.119)               (0.118)       
##                                                                 
## purchase                   -0.015***             -0.017***      
##                            (0.0003)              (0.0005)       
##                                                                 
## cumul                                            -0.021***      
##                                                   (0.001)       
##                                                                 
## ----------------------------------------------------------------
## Observations                43,669                43,669        
## R2                           0.076                 0.175        
## Max. Possible R2             0.670                 0.670        
## Log Likelihood            -22,508.520           -20,029.730     
## Wald Test            3,514.020*** (df = 3) 1,653.540*** (df = 4)
## LR Test              3,463.207*** (df = 3) 8,420.787*** (df = 4)
## Score (Logrank) Test 1,528.620*** (df = 3) 2,129.648*** (df = 4)
## ================================================================
## Note:                                *p<0.1; **p<0.05; ***p<0.01

Des paramètres qui dépendent du temps

On sait donc introduire dans un modèle de survie, le modèle de Cox, deux types de variables, des variables invariantes au cours du temps qui exercent un effet proportionnel constant au cours du temps, et d’autres donc la valeur variant au cours du temps peuvent affecter de manière différentielle les espérances de survie.

On peut encore envisager des variables dont l’état ne varient pas mais l’effet croit ou décroit avec le temps. Un modèle simple permet de rendre compte de ce type d’effet. Supposons que la survie S dépendent d’une variable X dont le paramètre est a. S=f(X,a). On peut supposer aussi bien que a soit fonction de la durée écoulée. Le temps s’accumulant ( une seconde à la fois conduit à 8600 seconde dans une journée) on aura volontier tendance à utiliser une fonction log : a(t) = a log(t)

Si a est positif l’effet s’accroit avec le temps, s’il est négatif il décroit.

C’est ce que nous allons tester.

la modélisation de la dynamique du paramètre est donc fonction de f(t). si c’est une fonction log, on suppose que que le paramètre s’accroit de manière décroissante avec le temps. si c’est une fonction exp c’est une croissance ou décroissance exponentielle selon le signe.

#cox
res.cox1 <- coxph(SurvObj ~  segment+ C_sms +C_email + C_mail +tt(C_mail), data =  c1, tt = function(x, t, ...) x * log(t+1))
res.cox1
## Call:
## coxph(formula = SurvObj ~ segment + C_sms + C_email + C_mail + 
##     tt(C_mail), data = c1, tt = function(x, t, ...) x * log(t + 
##     1))
## 
##                          coef exp(coef) se(coef)      z        p
## segmentBON-DIVERSITE -0.24912   0.77949  0.21604 -1.153 0.248864
## segmentINACTIF        3.00864  20.25976  0.15292 19.675  < 2e-16
## segmentJARDIN        -0.03030   0.97015  0.16828 -0.180 0.857090
## segmentJARDIN MAISON -0.12727   0.88050  0.19947 -0.638 0.523456
## segmentNON JARDIN     0.58647   1.79763  0.16777  3.496 0.000473
## segmentTOP-DIVERSITE -1.20650   0.29924  0.47155 -2.559 0.010511
## C_sms                 0.05988   1.06170  0.05226  1.146 0.251878
## C_email              -0.05168   0.94963  0.04523 -1.143 0.253214
## C_mail               -0.89194   0.40986  0.23671 -3.768 0.000165
## tt(C_mail)            0.08035   1.08367  0.04371  1.838 0.066007
## 
## Likelihood ratio test=3902  on 10 df, p=< 2.2e-16
## n= 4235, number of events= 3161
#plot(res.zph1)

Dans notre cas le fait de posseder le mail réduit fortement le risque, il est de 0,4 quand on possède l’addresse que quand on la possède pas. Pour comprendre la dynamique temporelle examinons la variable ttc( c_mail). le paramètre est de 0.08, autrement dit chaque fois que la durée double, l’effet de la possession du mail se réduit de 8%.

avec un peu d’arithmétique et de simulation on peut tracer le graphe de l’impact de cette information dans le temps. En un an l’impact du paramètre s’est réduit de moitié.

t<- as.data.frame(c(0:1000))  #on examine la variation sur 1000 jours
t$t<-t[,1]                    #on fixe la variable  temps
z= 1                          #un paramètre pour lineariser
t$logt<-log(z+t$t)            #on calcule le log du temps ( linéarisé)
beta<- (-.89194)              #la valeur primaire du paramètre de la variable dont le variable varie dans le temps
a<-0.08035                    #l'effet du temps sur le paramètre
t$parameter<-beta+(a*t$logt)  #la valeur du paramètre dans le temps
#representation graphique
ggplot(t,aes(x=t,y=parameter))+geom_point()+theme_minimal()

analyse des tickets de Caisse

Revenons à l’analyse des transactions, et examinons leurs distribution en fonction des montants. Elle semble suivre une loi exponentielle, ou puissance. On observe des valeurs négatives qui correspondent à des erreurs ou des remboursements.

ggplot(c1_pf, aes(Montant)) + geom_histogram(binwidth=5)+
labs(title="distribution des montants",
     y = "Nombre", x="Montant du ticket")+theme_classic()+xlim(-100, 300)
## Warning: Removed 963 rows containing non-finite values (stat_bin).
## Warning: Removed 2 rows containing missing values (geom_bar).

On ne prendra en compte que des valeurs strictement positives.

On exclue de l’analyse les achats opportunistes, ceux qui n’ont lieu qu’une fois et incite à prendre la carte de fidélité pour bénéficier d’un avantage immédiat.La carte joue pour ces clients le rôle d’une promotion. On pourrait s’interroger du la proportion d’entre eux qui aurait réaliser l’achat sans cette opportunité.

La distribution confirme le raisonnement dans la mesure où les montant sont de l’ordre d’une centaine d’euro. Curieusement une autre population de ticket à faible montant se manifeste : probablement des achateurs de babioles à 10 euros, qui se promenant en profite pour prolonger l’expérience de visite en souscrivant à la carte, mais ils sont peu nombreux, disons une centaine.

#c1_pf<-merge(c1_pf,c1, by="idclient",all.x=FALSE, all.y=FALSE, sort=TRUE)%>%filter(Montant>0)%>% filter(n.y>1)

ggplot(c1_pf, aes(Montant)) + geom_histogram(binwidth=5)+
labs(title="distribution des montants",
     y = "Nombre", x="Montant du ticket")+theme_minimal() +xlim(0, 500)
## Warning: Removed 1217 rows containing non-finite values (stat_bin).
## Warning: Removed 2 rows containing missing values (geom_bar).

l’évidence des 20/80

La bonne vieille loi du commerce : 20% des clients font 80% du chiffre d’affaire et de la marge et cette idée de concentrer sur eux l’essentiel des efforts même s’ils sont aussi la cible des concurrent. cette règle qui conduit à s’exposer à la disruption par une qualité excessive.

Cette loi de concentration est celle que représente la courbe de lorentz : https://en.wikipedia.org/wiki/Lorenz_curve. On utilise à cette fin le package [gglorenz] (avec le package https://github.com/jjchern/gglorenz)

l’enjeu c’est de mesurer la concentration du CA par les ventes les plus élevées.

Mediane<-round(median(c1_pf$Montant,na.rm = TRUE),2)
g1<-ggplot(c1_pf, aes(Montant)) + stat_ecdf(geom = "step")+
labs(title="Empirical Cumulative \n Density Function",y = "F(Proportion cumulée)", x="Montant du ticket")+theme_minimal()+xlim(0, 200)+ annotate("text", x=25, y=0.9, label= paste0("Mediane=",Mediane))


gini<-round(ineq(c1_pf$Montant,type = c("Gini")),2)

c1_pf<-c1_pf %>% filter(Montant>0)
g2<-ggplot(c1_pf, aes(Montant)) +stat_lorenz(desc = TRUE,size=1.2,color="Darkgreen") +coord_fixed() +geom_abline(linetype = "dashed") +theme_minimal() + annotate("text", x=0.15, y=0.9, label= paste0("indice de Gini=",gini))

library(gridExtra)
grid.arrange(g1,g2,ncol=2)
## Warning: Removed 3031 rows containing non-finite values (stat_ecdf).

Evolution des montants au cours du temps

On va raisonner en séquences d’achats et les ordonner pour étudier l’évolution des montants moyens et des durées interachats. L’hypothèse qu’on sert a tester est celle d’une étude analogue que nous avons déjà effectuée en XXXX, sur des données similaire : un distributeurs spécialisé. L’un oeuvre dans l’automobile l’autre dans le bricolage et la jardinerie.

On y retrouve le même phénomène.

Pour les montant d’achats, quelques soit les consommateurs classés en termes de nombre d’achat réalisé sur la période, on observe un effet sur les premières périodes : le montant est maximal au premier achat, il se réduit sur une séquence de deux ou trois achats, puis se maintient à un niveau stationnaire qui ne dépend pas de la segmentation.

En explorant avec une courbe d’ajustement lissée, on s’aperçoit que les clients qui produiront le plus d’achats sont moins affectés par l’effets d’opportunités, leur dépenses moyennes sont moins elevées que ceux qui ne feront que quelques achats. Mais tous se rejoignent au niveau stationnaire.dès le 4ème ou cinquième achat.

Seq1 <- c1_pf[order(c1_pf$idclient,c1_pf$Date),]
Seq1 <-Seq1%>% group_by(idclient)%>% mutate(rank = dense_rank(Date))%>% ungroup()
Seq1$Classe_freq[Seq1$n==2] <-"2 achats"
## Warning: Unknown or uninitialised column: 'Classe_freq'.
Seq1$Classe_freq[Seq1$n==3] <-"3 achats"
Seq1$Classe_freq[Seq1$n==4] <-"4 achats"
Seq1$Classe_freq[Seq1$n==5] <-"5 achats"
Seq1$Classe_freq[Seq1$n>5 & Seq1$n<11 ] <-"de  5 à 10 achats"
Seq1$Classe_freq[Seq1$n>10 & Seq1$n<16 ] <-"de 11 à 20 achats" 
Seq1$Classe_freq[Seq1$n>15 & Seq1$n<21 ] <-"de 16 à 20 achats"
Seq1$Classe_freq[Seq1$n>20 & Seq1$n<26 ] <-"de 21 à 25 achats"
Seq1$Classe_freq[Seq1$n>25 & Seq1$n<31 ] <-"de 26 à 30 achats"
Seq1$Classe_freq[Seq1$n>30 & Seq1$n<41 ] <-"de 31 à 40 achats"
Seq1$Classe_freq[Seq1$n>40 & Seq1$n<51 ] <-"de 41 à 50 achats"
Seq1$Classe_freq[Seq1$n>50] <-"plus de 30 achats"

Seq2<-aggregate(Montant~rank+Classe_freq,data=Seq1,FUN=mean)
Seq2$Classe_freq<-as.factor(Seq2$Classe_freq)

ggplot(Seq2,aes(x=rank,y=Montant,group=Classe_freq))+geom_line(aes(color=Classe_freq),size=1.1)+xlim(0,30)+scale_color_viridis(discrete = TRUE)+xlim(1,9)
## Warning: Removed 383 rows containing missing values (geom_path).

fit<-lm(log(Montant)~rank+Classe_freq,data=Seq1)
summary(fit)
## 
## Call:
## lm(formula = log(Montant) ~ rank + Classe_freq, data = Seq1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -6.8548 -0.6476  0.0491  0.6920  4.6310 
## 
## Coefficients:
##                                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                   4.2182373  0.0314436 134.152  < 2e-16 ***
## rank                         -0.0041084  0.0002223 -18.481  < 2e-16 ***
## Classe_freq3 achats          -0.2305502  0.0430184  -5.359 8.39e-08 ***
## Classe_freq4 achats          -0.3871018  0.0411897  -9.398  < 2e-16 ***
## Classe_freq5 achats          -0.4249959  0.0409475 -10.379  < 2e-16 ***
## Classe_freqde  5 à 10 achats -0.4895213  0.0336347 -14.554  < 2e-16 ***
## Classe_freqde 11 à 20 achats -0.5403062  0.0340039 -15.890  < 2e-16 ***
## Classe_freqde 16 à 20 achats -0.5939521  0.0345464 -17.193  < 2e-16 ***
## Classe_freqde 21 à 25 achats -0.5402427  0.0353234 -15.294  < 2e-16 ***
## Classe_freqde 26 à 30 achats -0.6358405  0.0356450 -17.838  < 2e-16 ***
## Classe_freqde 31 à 40 achats -0.5535701  0.0346322 -15.984  < 2e-16 ***
## Classe_freqde 41 à 50 achats -0.5589418  0.0348961 -16.017  < 2e-16 ***
## Classe_freqplus de 30 achats -0.6499348  0.0341970 -19.006  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.025 on 55218 degrees of freedom
## Multiple R-squared:  0.03028,    Adjusted R-squared:  0.03007 
## F-statistic: 143.7 on 12 and 55218 DF,  p-value: < 2.2e-16
g<-ggplot(Seq1, aes(x=rank,y=Montant,group=Classe_freq))+geom_point(aes(color=Classe_freq))+geom_smooth(method = "loess",aes(color=Classe_freq))+xlim(0,10)+scale_color_viridis(discrete = TRUE)+scale_y_continuous(trans='log10')
suppressWarnings(print(g))

Evolution des durées inter-achat au cours du temps

Pour analyser l’évolution des durées inter-achats, on calcule pour chaque segment définis par le nombre total d’achat des ajustements lissés à l’ordre de l’acte d’achat. En procédant ainsi on contrôle l’effet de la succession de l’effet de fréquence propre à chaque individu.

Un modèle de régression simple complète l’analyse descriptive. Il y a bien un effet d’interaction mais faible, en-deça de la quinzaine d’achat. Les achats fréquents, ceux des vrais fidèles, ont une période stationnaire.

pts<-Seq1 %>% group_by(idclient) %>% mutate(Points, ptscum = cumsum(Points))%>% mutate(Montant, prev = lead(Montant, order_by = rank))%>%  mutate(Date, duree = as.numeric(lead(Date, order_by = rank)-Date)) %>% ungroup()


g<-ggplot(pts, aes(x=rank,y=duree,group=Classe_freq))+geom_smooth(method = "loess",aes(color=Classe_freq))+xlim(0,10)+scale_color_viridis(discrete = TRUE)+scale_y_continuous(trans='log10')
suppressWarnings(print(g))

fit1<-lm(log(duree+1)~rank+Classe_freq,data=pts)

fit2<-lm(log(duree+1)~rank+Classe_freq +rank*Classe_freq,data=pts)
stargazer(fit1,fit2,type="text")
## 
## =========================================================================================
##                                                     Dependent variable:                  
##                                   -------------------------------------------------------
##                                                       log(duree + 1)                     
##                                               (1)                         (2)            
## -----------------------------------------------------------------------------------------
## rank                                       0.006***                    0.004***          
##                                             (0.001)                     (0.001)          
##                                                                                          
## Classe_freq3 achats                          0.128                      -0.357           
##                                             (0.207)                     (0.439)          
##                                                                                          
## Classe_freq4 achats                          0.156                      -0.332           
##                                             (0.196)                     (0.334)          
##                                                                                          
## Classe_freq5 achats                          0.151                      -0.082           
##                                             (0.193)                     (0.304)          
##                                                                                          
## Classe_freqde 5 à 10 achats                0.859***                     0.432**          
##                                             (0.168)                     (0.188)          
##                                                                                          
## Classe_freqde 11 à 20 achats               1.726***                    1.424***          
##                                             (0.169)                     (0.190)          
##                                                                                          
## Classe_freqde 16 à 20 achats               2.255***                    2.101***          
##                                             (0.170)                     (0.195)          
##                                                                                          
## Classe_freqde 21 à 25 achats               2.772***                    2.470***          
##                                             (0.172)                     (0.201)          
##                                                                                          
## Classe_freqde 26 à 30 achats               3.494***                    3.412***          
##                                             (0.173)                     (0.204)          
##                                                                                          
## Classe_freqde 31 à 40 achats               4.158***                    4.109***          
##                                             (0.170)                     (0.192)          
##                                                                                          
## Classe_freqde 41 à 50 achats               4.111***                    3.985***          
##                                             (0.171)                     (0.193)          
##                                                                                          
## Classe_freqplus de 30 achats               4.608***                    4.656***          
##                                             (0.169)                     (0.169)          
##                                                                                          
## rank:Classe_freq3 achats                                                 0.326           
##                                                                         (0.260)          
##                                                                                          
## rank:Classe_freq4 achats                                                0.248*           
##                                                                         (0.137)          
##                                                                                          
## rank:Classe_freq5 achats                                                 0.095           
##                                                                         (0.096)          
##                                                                                          
## rank:Classe_freqde 5 à 10 achats                                       0.110***          
##                                                                         (0.022)          
##                                                                                          
## rank:Classe_freqde 11 à 20 achats                                      0.049***          
##                                                                         (0.014)          
##                                                                                          
## rank:Classe_freqde 16 à 20 achats                                       0.018*           
##                                                                         (0.011)          
##                                                                                          
## rank:Classe_freqde 21 à 25 achats                                      0.028***          
##                                                                         (0.009)          
##                                                                                          
## rank:Classe_freqde 26 à 30 achats                                        0.007           
##                                                                         (0.008)          
##                                                                                          
## rank:Classe_freqde 31 à 40 achats                                        0.004           
##                                                                         (0.005)          
##                                                                                          
## rank:Classe_freqde 41 à 50 achats                                        0.007           
##                                                                         (0.004)          
##                                                                                          
## rank:Classe_freqplus de 30 achats                                                        
##                                                                                          
##                                                                                          
## Constant                                   4.624***                    4.626***          
##                                             (0.161)                     (0.161)          
##                                                                                          
## -----------------------------------------------------------------------------------------
## Observations                                51,036                      51,036           
## R2                                           0.158                       0.159           
## Adjusted R2                                  0.158                       0.159           
## Residual Std. Error                   3.692 (df = 51023)          3.690 (df = 51013)     
## F Statistic                       799.558*** (df = 12; 51023) 439.139*** (df = 22; 51013)
## =========================================================================================
## Note:                                                         *p<0.1; **p<0.05; ***p<0.01

L’effet des points de fidélité

Dans cette troisème partie de l’étude nous reste à étudier l’effet de la distribution des points de fidélité sur d’une part les dépenses éffectuées au cours des prochains achats, et d’autres part sur la fréquence de répétition, autrement dit sur la durée inter-achat.

Il s’agira de mieux apprécier les programmes de fidélisation moins dans leur capacité à segmenter et donc à choisir en connaissance de cause là où il faut investir, mais dans l’appréciation de l’ampleur de leur réponse à l’égard des récompenses qui leurs sont accordées.

Effets des points gagnés sur le montant des dépenses

Pour apprécier le problème quelques éléments descriptifs sont utiles. D’une part la distribution des points délivrés, d’autre part la corrélation entre le montant du ticket de caisse et les points distribués. On

A droite la distribution des mois est représentée; elle est troncquée, la médiane est en dessous de 10 achats. Au delà de 50 points les cas sont très rare.

A gauche le diagramme traduit une écolutrion du barème, si globalement la coorelation est forte, meême determiste par l’allure des alignement de pointsd, on observe un décalege de couleurs qui relevent une augmentayion de la pente :; de 2à10 à 2019 la récompense s’accroit dans un rapport quasi de de 100 euros=15 points directement lisible sur le graphe.

gp1<-ggplot(Seq1, aes(x=Points))+geom_histogram(binwidth = 1)+xlim(0, 70)+theme_minimal()
Seq1$year<-year(Seq1$Date)
gp2<-ggplot(Seq1, aes(x=Montant, y=Points, color=year))+geom_point(size=0.8)+xlim(0,3000)+ylim(0, 400)+theme_minimal()+geom_smooth()
grid.arrange(gp2,gp1,ncol=2)
## Warning: Removed 6 rows containing non-finite values (stat_smooth).
## Warning: Removed 6 rows containing missing values (geom_point).
## Warning: Removed 1 rows containing missing values (geom_smooth).
## Warning: Removed 426 rows containing non-finite values (stat_bin).
## Warning: Removed 2 rows containing missing values (geom_bar).

On doit jouer sur le temps, effet des points acquis ou cumulé à t sur les ventes à t+1

on observe un bel effet d’interaction : si le stock de point est plus élevé que la moyenne( ex 1 sd audessus) alors l’effet est negatif, si c’est endessous il devient positif.

l’interaction se produit aussi avec le rang de l’achat, l’effet des point obtenu est positif quand le rang est faible, il devient même négatif quand il est élevé.

pts<-Seq1 %>% group_by(idclient) %>% mutate(Points, ptscum = cumsum(Points))%>% mutate(Montant, total_1 = lag(Montant, order_by = rank))%>% ungroup()
sum(is.na(pts$ptscum))
## [1] 0
sum(is.na(pts$total_1))
## [1] 4195
pts<-pts %>% drop_na(total_1) 

ggplot(pts, aes(x=ptscum))+geom_histogram()+scale_x_continuous(trans='log10')
## Warning: Transformation introduced infinite values in continuous x-axis
## Warning: Removed 1 rows containing non-finite values (stat_bin).

ggplot(pts, aes(x=Points, y=ptscum , color=year))+geom_point()+scale_x_continuous(trans='log10')+scale_y_continuous(trans='log10')
## Warning: Transformation introduced infinite values in continuous x-axis
## Warning: Transformation introduced infinite values in continuous y-axis

#pts$ptscum_sq <- with(pts, cut(ptscum, breaks=quantile(ptscum, probs=seq(0,1, by=0.20), na.rm=TRUE), include.lowest=TRUE))


M1<-lmer(total_1~Montant+Points+ptscum +(Points | idclient),data=pts)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model is nearly unidentifiable: very large eigenvalue
##  - Rescale variables?
summary(M1)
## Linear mixed model fit by REML ['lmerMod']
## Formula: total_1 ~ Montant + Points + ptscum + (Points | idclient)
##    Data: pts
## 
## REML criterion at convergence: 608892.2
## 
## Scaled residuals: 
##    Min     1Q Median     3Q    Max 
## -8.139 -0.346 -0.137  0.137 37.526 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev. Corr 
##  idclient (Intercept) 3146.155 56.091        
##           Points         1.177  1.085   -0.16
##  Residual             7857.364 88.642        
## Number of obs: 51036, groups:  idclient, 4177
## 
## Fixed effects:
##              Estimate Std. Error t value
## (Intercept) 70.727177   1.185873  59.641
## Montant      0.256929   0.030200   8.508
## Points      -1.221175   0.181704  -6.721
## ptscum       0.014243   0.002969   4.797
## 
## Correlation of Fixed Effects:
##         (Intr) Montnt Points
## Montant -0.192              
## Points   0.080 -0.956       
## ptscum  -0.230  0.122 -0.132
## convergence code: 0
## Model is nearly unidentifiable: very large eigenvalue
##  - Rescale variables?
#avec nmle
M2<-lme(total_1~ptscum+Points+Points*rank+Points*ptscum,random=~1|idclient/rank,data=pts)
summary(M2)
## Warning in pt(-abs(tVal), fDF): production de NaN
## Linear mixed-effects model fit by REML
##  Data: pts 
##        AIC      BIC    logLik
##   608631.1 608710.6 -304306.5
## 
## Random effects:
##  Formula: ~1 | idclient
##         (Intercept)
## StdDev:    29.55902
## 
##  Formula: ~1 | rank %in% idclient
##         (Intercept) Residual
## StdDev:    89.19994 20.51066
## 
## Fixed effects: total_1 ~ ptscum + Points + Points * rank + Points * ptscum 
##                  Value Std.Error    DF   t-value p-value
## (Intercept)   63.61500 0.8636699 46857  73.65661       0
## ptscum         0.14594 0.0045039    -3  32.40301     NaN
## Points         0.65609 0.0452665    -3  14.49395     NaN
## rank          -1.08121 0.0371416 46857 -29.11039       0
## Points:rank   -0.02281 0.0020708    -3 -11.01543     NaN
## ptscum:Points -0.00012 0.0000848    -3  -1.43349     NaN
##  Correlation: 
##               (Intr) ptscum Points rank   Pnts:r
## ptscum        -0.217                            
## Points        -0.449  0.103                     
## rank          -0.094 -0.712  0.055              
## Points:rank    0.092 -0.119 -0.166 -0.190       
## ptscum:Points  0.208 -0.140 -0.471  0.186 -0.608
## 
## Standardized Within-Group Residuals:
##         Min          Q1         Med          Q3         Max 
## -1.38999021 -0.08312324 -0.03542009  0.03287987  9.71724009 
## 
## Number of Observations: 51036
## Number of Groups: 
##           idclient rank %in% idclient 
##               4177              51035
#avec log
pts_ln<-pts %>%mutate(total_1_L=log(total_1+1),Montant_l=log(Montant+1), Points_l=log(Points+1),ptscum_l=log(ptscum+1),rank_l=log(rank+1))
M3<-lme(total_1_L~ptscum+Points_l+Points_l*rank_l+Points_l,random=~1|idclient/rank,data=pts_ln)
summary(M3)
## Warning in pt(-abs(tVal), fDF): production de NaN
## Linear mixed-effects model fit by REML
##  Data: pts_ln 
##        AIC      BIC   logLik
##   131400.8 131471.5 -65692.4
## 
## Random effects:
##  Formula: ~1 | idclient
##         (Intercept)
## StdDev:   0.2953589
## 
##  Formula: ~1 | rank %in% idclient
##         (Intercept)  Residual
## StdDev:   0.7804452 0.3391645
## 
## Fixed effects: total_1_L ~ ptscum + Points_l + Points_l * rank_l + Points_l 
##                     Value   Std.Error    DF   t-value p-value
## (Intercept)      4.148724 0.026754820 46857 155.06454       0
## ptscum           0.001650 0.000037022    -2  44.57821     NaN
## Points_l         0.192485 0.012530136    -2  15.36177     NaN
## rank_l          -0.345590 0.010759345 46857 -32.12001       0
## Points_l:rank_l -0.048865 0.004727302    -2 -10.33677     NaN
##  Correlation: 
##                 (Intr) ptscum Pnts_l rank_l
## ptscum           0.188                     
## Points_l        -0.822  0.101              
## rank_l          -0.900 -0.363  0.687       
## Points_l:rank_l  0.745 -0.164 -0.930 -0.713
## 
## Standardized Within-Group Residuals:
##         Min          Q1         Med          Q3         Max 
## -1.95398092 -0.24666089  0.02285625  0.25898086  1.97378247 
## 
## Number of Observations: 51036
## Number of Groups: 
##           idclient rank %in% idclient 
##               4177              51035
stargazer(M1,M2,M3, type="text")
## 
## =============================================================
##                                Dependent variable:           
##                     -----------------------------------------
##                               total_1             total_1_L  
##                        linear        linear        linear    
##                     mixed-effects mixed effects mixed effects
##                          (1)           (2)           (3)     
## -------------------------------------------------------------
## Montant               0.257***                               
##                        (0.030)                               
##                                                              
## Points                -1.221***       0.656                  
##                        (0.182)       (0.045)                 
##                                                              
## rank                                -1.081***                
##                                      (0.037)                 
##                                                              
## Points:rank                          -0.023                  
##                                      (0.002)                 
##                                                              
## ptscum:Points                        -0.0001                 
##                                     (0.0001)                 
##                                                              
## ptscum                0.014***        0.146         0.002    
##                        (0.003)       (0.005)      (0.00004)  
##                                                              
## Points_l                                            0.192    
##                                                    (0.013)   
##                                                              
## rank_l                                            -0.346***  
##                                                    (0.011)   
##                                                              
## Points_l:rank_l                                    -0.049    
##                                                    (0.005)   
##                                                              
## Constant              70.727***     63.615***     4.149***   
##                        (1.186)       (0.864)       (0.027)   
##                                                              
## -------------------------------------------------------------
## Observations           51,036        51,036        51,036    
## Log Likelihood      -304,446.100  -304,306.500   -65,692.400 
## Akaike Inf. Crit.    608,908.200   608,631.100   131,400.800 
## Bayesian Inf. Crit.  608,979.000   608,710.600   131,471.500 
## =============================================================
## Note:                             *p<0.1; **p<0.05; ***p<0.01

On utilise une fonction de Ape pour décomposer les élements de la variance. Dans notre cas la variabilité des individus représente 9.5% de la variance de la composante alétoire du modèle, le rang de l’achat pour 86,0% 4,5% doivent être attribué à des causes autres, propres à chaque achat.

#avec le package Ape
v <- varcomp(M2, TRUE, FALSE)
v
##   idclient       rank     Within 
## 0.09444714 0.86007834 0.04547452 
## attr(,"class")
## [1] "varcomp"
plot(v)

une autre fonction r.squaredGLMM, du Package MuMln donne les part de variance expliquée par la composante fixe (les variables explicatives) et la composante aléatoire que nous venons d’analyser. Le résultat est peu convaincant : l’achat précédent, le nombre de points acquis précédemment et le cumul des points n’expliquent que 6.68% de la variance des montants des tickets de caisse. C’est statisquement significatif, mais faible en terme d’effet. Ce qu’on dépense dépend des circonstances, et l’effet des programmes de fidélité au mieux accroit les dépenses dans un ordre de 1%. C’est faible mais pas nul si la croissance n’est pas plus forte que deux ou trois %.

library(MuMIn)

r.squaredGLMM(M2)
## Warning: 'r.squaredGLMM' now calculates a revised statistic. See the help
## page.
##             R2m       R2c
## [1,] 0.06684168 0.9575651

En dépit du pouvoir très faiblement explicatif de nos variables effets, on s’aperçoit que l’effet d’interaction est sensible avec les graphes obtenus par la fonction effect.

On observe la relation entre les points est le montant passer d’une relation positive à une relation négative à mesure que le nombre de point cumulé est élevé ou que le nombre d’achat ( le rank) s’accroît. A mesure que le client est fidélisé, les récompenses ne jouent plus. On trouvera dans ce fait une autre illustration du mecanisme des motivations intrinsèques et extrinsèque. La récompense monétaire joue de moins en moins avec le temps. Elle joue quand l’engagement est faible.

ef <- Effect(c("Points","ptscum"), M2)
plot(ef)

ef <- Effect(c("Points","rank"),quantiles=seq(0, 1, by=0.25), M2)
plot(ef)

Effets des points gagnés sur la durée inter achat

On laisse le soin au lecteur d’ajuster le code précédent à l’étude des durées inter-achats. Il s’amusera à produire d’autres tests, on l’encourage notamment à étudier les auto correlations des durées inter-achat, et d’étudier plus finement la dépendance temporelle, et celle de la corrélation du montant des dépenses et des durée inter-chat.

Conclusion

A partir de ce set de données, bien d’autres analyses peuvent être menées. La première est de prendre en compte une dimension plus qualitative, celle de la nuture des achats. Dans ce domaine de consommation, on s’attend à ce que les besoins en alimentation animales, pèsent sur la fidélité différemment que ceux de renouveller les plantes du balcons. Nous avons ces détails avec le détails du tickets de caisse. Dans le même esprit on peut peut-être tenir compte de données géographiques, dont nous avons masqué les données autant pour limiter l’étude à un champs particulier, que pour éviter toute identification secondaire.

Deux outils complémentaires ont été présenté pour analyser la dynamique des ventes d’un segment adhérant à un programme de fidélisation, ils concernent deux niveaux d’analyse :

Sur le plan relationnel, l’étude, qui n’a pas été systématique et qui n’a pas testé toutes les variables, révèle cependant que la durée de vie des client est assez lié à des marqueurs d’engagement initiaux : notamment le fait de donner son adresse terrestre. Elle montre aussi que l’adhésion à un programme de fidélité répond largement à une motivation opportuniste, notamment quand les achat sont monétairement importants. 20% des adhérent disparaissent après la première transaction. Au-dela on observe une sélection entre ceux qui réalisent des achats réguliers et ceux qui se fatiguent rapidement. On observera cependant que cette information dépend du temps, en testant un modèle à paramètre variable, on s’apercoit ainsi qu’avec le temps la variable d’nagement qu’est le fait d’avoir donner son adresse, pèse de moins en moins dans le temps.

L’expérience compte. Les modèles à variables variant avec le temps justifient l’impact d’une part de la fréquentation des points de ventes : chaque fois qu’un achat est réalisé, le risque est réduit, et d’autre part de l’habitude mesurée comme le cumul des achats dans le temps. Cette dernière variable acrroit d’ailleurs substatiellement l’ajustement du modèle. On en suppose que si l’expérience est gratifiante; elle pésera d’autant plus.

le modèle comportemental qui se dégage s’appuie sur trois processus * un engagement initial qu’on peut identifier dans certains actes, celui de donner ses identifiants étant le plus évident * un effet opportiniste des récompenses offertes qui pèse à l’initiation de la relation * la réalité des expériences, les visites et les nouveaux achats qui surdeterminent le futur de la relation.

BENAVENT, CHRISTOPHE, and DOMINIQUE CRIÉ. 1998. “MESURER L’EFFICACITÉ DES CARTES DE FIDÉLITÉ.” Décisions Marketing, no. 15: 83–90. http://www.jstor.org/stable/40592920.

Meyer-Waarden, Lars, and Christophe Benavent. 2006. “The Impact of Loyalty Programmes on Repeat Purchase Behaviour.” Journal of Marketing Management 22 (1-2): 61–88. doi:10.1362/026725706776022308.

———. 2009. “Grocery Retail Loyalty Program Effects: Self-Selection or Purchase Behavior Change?” Journal of the Academy of Marketing Science 37 (3): 345–58. doi:10.1007/s11747-008-0123-z.

Tung, Jenny, Elizabeth A. Archie, Jeanne Altmann, and Susan C. Alberts. 2016. “Cumulative Early Life Adversity Predicts Longevity in Wild Baboons.” Nature Communications 7 (April): 11181. https://doi.org/10.1038/ncomms11181.


  1. tiré de Tung et al. (2016), les deux courbes représentent la survie de babouines exposées à plusieurs conditions adverses au cours de leur enfance