Partager la publication "Quelle est la durée de vie de mes articles sur mon site ? R – II"
Cette page est la suite de l’article Quelle est la durée de vie de mes articles sur mon site ? R – I
Suite du Code Source :
Vous pouvez aussi récupérer le source en entier gratuitement dans notre boutique à l’adresse : https://www.anakeyn.com/boutique/produit/script-r-duree-de-vie-des-articles/ .
Significativité du trafic « articles marketing » dans les mois suivants la publication.
Dans cette partie nous allons généraliser le calcul des distributions précédentes sur toute la période étudiée (7,5 ans) et vérifier à quel moment les « Articles Marketing » n’apportent plus un trafic significatif.
Statistiquement cela revient à tester pour tous les mois l’hypothèse :
H0 : La médiane de la distribution est = 0 (i.e. il y a plus de pages avec 0 vues qu’avec 1 ou plusieurs vues)
H1 : La médiane de la distribution est > 0
Afin d’effectuer ce test nous allons utiliser le SIGN.test qui est implémenté dans R. On utilisera ce test en comparant nos distributions par rapport à une distribution nulle.
Une p-valeur >0.05 indique que l’hypothèse H0 ne peut être rejetée.
Qu’est-ce que la p-valeur ?
Profitons-en pour rappeler la définition de la p-valeur dont on parle souvent ici !
Attention !!! Prendre son élan :
« Dans un test statistique, la valeur-p (en anglais p-value pour probability value), parfois aussi appelé p-valeur, est la probabilité pour un modèle statistique donné sous l’hypothèse nulle d’obtenir la même valeur ou une valeur encore plus extrême que celle observée. »
Bon, on retiendra la définition plus triviale :
« La p-valeur est la probabilité de se tromper en rejetant l’hypothèse nulle. »
Utilisation du SIGN.test de R pour tester la significativité du trafic « Articles Marketing »
############################################################################################# # Utilisation du SIGN.test pour tester la significativité des distributions. ############################################################################################# #initialisation : #Pour enregistrer les données du SIGN.test pour toutes les distributions, et aussi les données #pour le comparatif par rapport à la taille de l'échantillons et pour la méthode via calcul de #l'intervalle de confiance de proportion dfAMPValue <- data.frame(pValue=double(), #pour SIGN.test conf.int.inf = double(), #facultatif conf.int.sup = double(), #facultatif statistic = double(), #pour visualisation stat vs size myNotNas = double(), #pour méthode SIGN et IC Proportion myNotNull = double(), #pour méthode IC Proportion myMedian = double()) #pour méthode IC Proportion dfAMAllMonthsPV <- data.frame(ThisPeriodPV <- double(), numMonth <- integer()) myAMMd <- 0.01 #médiane de l'hypothèse nulle : 0 ne marche pas #-> à mon avis le test est que la médiane soit inférieure #à cette valeur donc < 0 ne donne rien alors que < 0.01 #détecte les 0. #Rem cela fonctionne pareil avec SAS et Python myAMCl <- 0.95 #niveau de confiance souhaité myLastMonth <- 90 #dernier mois à investiguer 7,5 années for (x in (1:myLastMonth)) { #on boucle sur tous les mois #Appel à la fonction de récupération d'une ditribution dfAMThisMonthPV <- getMyDistribution(myPageViews=dfAMPageViews, myArticles=myArticles, myNumPeriode=x, myNbrOfDays=30, myLastDate=dfAMPageViews[nrow(dfAMPageViews),"date"], myTestType="AM") #pour exporter vers sas on sauvegarde toutes les distributions dfAMThisMonthPV$numMonth <- x dfAMAllMonthsPV <- rbind(dfAMAllMonthsPV, dfAMThisMonthPV) res <- SIGN.test(dfAMThisMonthPV$ThisPeriodPV, y=NULL, md=myAMMd, alternative="greater", conf.level = myAMCl) #str(res) dfAMPValue[x, "pValue"] <- res$p.value dfAMPValue[x, "conf.int.inf"] <- res$conf.int[1] #borne inférieure de l'intervalle de confiance dfAMPValue[x, "conf.int.sup"] <- res$conf.int[2] #borne supérieure de l'intervalle de confiance dfAMPValue[x, "statistic"] <- res$statistic #nombre de valeurs > 0 dfAMPValue[x, "myNotNas"] <- sum(!is.na(dfAMThisMonthPV$ThisPeriodPV)) #taille de l'échantillon #nombre de valeurs > 0 #calculé à la main hors de SIGN.test pour le calcul de l'IC de proportion dfAMPValue[x, "myNotNull"] <- sum(!(dfAMThisMonthPV[!is.na(dfAMThisMonthPV$ThisPeriodPV), "ThisPeriodPV"]==0)) dfAMPValue[x, "myMedian"] <- median(!is.na(dfAMThisMonthPV$ThisPeriodPV)) #médiane } #str(dfAMAllMonthsPV) #Export des distributions si besoin write.csv2(dfAMAllMonthsPV, file = "dfAMAllMonthsPV.csv", row.names=FALSE) head(dfAMPValue, n=20) #Visualisation de la p.valeur du SIGN.test myfirstMonthPValueUpper <- which.first(dfAMPValue$pValue > 0.05) ggplot(data=dfAMPValue, aes(x=as.numeric(row.names(dfAMPValue)), y=pValue)) + geom_line() + #, size=myNotNas geom_vline(xintercept= myfirstMonthPValueUpper, color="green") + geom_hline(yintercept = 0.05, color="red") + xlab("Nombre de mois") + ylab("P-Valeur") + labs(title = paste("L'hypothèse nulle est vérifiée dès le mois", myfirstMonthPValueUpper, "(ligne verte)" ), subtitle = "La ligne rouge indique la p Valeur à 0.05.", caption = paste("P.valeur SIGN.test médiane ", myAMMd, " niveau de confiance ", myAMCl)) #sauvegarde du dernier ggplot ggsave(filename = "AM-SIGN-Test-P-Value.jpg", dpi="print")
Comme on le voit sur le graphique de la p-valeur, cela correspond à dire que l’apport de trafic cesse dès le 10ème mois.
Rem : on pourrait se poser la question de savoir si la p-valeur augmente du fait que la taille de l’échantillon de pages diminue. (ce qui est peu probable ici car on voit que les mois 11 et 12 sont meilleurs que le mois 10). Vérifions toutefois cela visuellement.
Comparatif Statistique vs taille de l’échantillon
Comparons la statistique, c’est-à-dire ici, les pages avec vues > 0, avec la taille de l’échantillon donnés par myNotNas, et la moitié de ce dernier.
#comparons la statistique càd ici les pages avec vues > 0 #vs la taille de l'échantillon donnés par myNotNas, et la moitié de ce dernier ggplot(data=dfAMPValue, aes(x=as.numeric(row.names(dfAMPValue)), y=statistic)) + geom_line() + geom_line(aes(x=as.numeric(row.names(dfAMPValue)), y=myNotNas), color="red") + geom_line(aes(x=as.numeric(row.names(dfAMPValue)), y=statistic), color="blue") + geom_line(aes(x=as.numeric(row.names(dfAMPValue)), y=myNotNas/2), color="black") + xlab("Nombre de mois") + ylab("Nbre de pages vues > 0 (bleu) | taille échantillon (rouge) ") + labs(title = "Le nombre de pages avec vues > 0 baisse plus vite \n que la taille de l'échantillon", subtitle = "La courbe bleu s'approche rapidement de la ligne noire \n qui représente la moitié de l'échantillon", caption = paste("Evolution mensuelle du Nbr de pages vues > 0 vs Taille échantillon \n Médiane de test", myAMMd, " niveau de confiance ", myAMCl)) ggsave(filename = "AM-sup0-SampleSize.jpg", dpi="print")
Autre méthode : calcul de l’intervalle de confiance pour une proportion
Nous pourrions aussi résoudre le problème en calculant l’intervalle de confiance d’une proportion.
Cela peut vous êtes utile si vous n’avez pas un équivalent de SIGN.test dans votre langage.
Nous travaillons ici sur la proportion de pages avec vues > 0 vs la taille de l’échantillon pour un mois donné.
Pour le calcul on utilisera la formule approximative :
Où :
- p est la proportion : pages avec vues > 0 / taille de l’échantillon pour le mois
- n est la taille de l’échantillon
- z est la valeur souhaitée pour le niveau de confiance, par exemple :
- 1,96 pour 95%
- 2,57 pour 99 %
################################################################################### # vérifions en calculant l'intervalle de confiance à 95% pour une proportion # avec les données observées. dfAMPValue$prop <- dfAMPValue$myNotNull/dfAMPValue$myNotNas #proportion #Intervalle de confiance à 95% pour une proportion dfAMPValue$confIntProportion <- 1.96 * sqrt((dfAMPValue$prop*(1-dfAMPValue$prop))/dfAMPValue$myNotNas) #borne inférieure dfAMPValue$propCIinf <- dfAMPValue$prop-dfAMPValue$confIntProportion #borne superieure dfAMPValue$propCIsup <- dfAMPValue$prop+dfAMPValue$confIntProportion #Première valeur de la borne inférieure sous 0.5 firstpropCIinfUnder <- which.first(dfAMPValue$propCIinf <= 0.5) ################################################################################### ggplot(data=dfAMPValue, aes(x=as.numeric(row.names(dfAMPValue)), y=prop)) + geom_line() + geom_line(aes(x=as.numeric(row.names(dfAMPValue)), y=propCIsup), color="blue") + geom_line(aes(x=as.numeric(row.names(dfAMPValue)), y=propCIinf), color="blue") + geom_hline(yintercept = 0.5, color="red") + geom_vline(xintercept= firstpropCIinfUnder, color="green") + xlab("Nombre de mois") + ylab("proportion avec intervalle de confiance (bleu) ") + labs(title = paste("L'hypothèse nulle est vérifiée dès le mois ", firstpropCIinfUnder ), subtitle = "La valeur inférieure de l'intervalle de confiance passe sous la barre des 0.5", caption = paste("Proportion de pages vues > 0 pour chaque distribution mensuelle \n niveau de confiance ", myAMCl)) ggsave(filename = "AM-PropPVsup1.jpg", dpi="print")
On obtient le même résultat qu’avec la méthode du SIGN.test, soit le mois 10.
Résultats pour les valeurs lissées
Par curiosité, recréons la courbe précédente en lissant les valeurs (méthode LOESS)
################################################################################### #en Lissage Loess #Calcul Valeurs lissées myAMLoess <- loess((myNotNull/myNotNas)~row.names(dfAMPValue), dfAMPValue ) str(myAMLoess) myAMLoess$fitted #valeurs lissées #Première valeur lissée sous la barre des 0.5 i.e mediane = 0 firstAMLoessUnder <- which.first(myAMLoess$fitted <= 0.5) #le premier # valeurs lissées inférieures : myAMLoess$conf.int.inf <- myAMLoess$fitted - (myAMLoess$s/2) #Première valeur de la borne inférieure de l'IC lissée sous la barre des # 0.5 i.e mediane = 0 firstAMLoessCIFUnder <- which.first(myAMLoess$conf.int.inf <= 0.5) #comparatif du rapport entre les Dist > 0 / myNotnas ggplot(data=dfAMPValue, aes(x=as.numeric(row.names(dfAMPValue)), y=myNotNull/myNotNas)) + geom_line() + geom_smooth() + geom_hline(yintercept = 0.5, color="red") + geom_vline(xintercept= firstAMLoessCIFUnder, color="green") + xlab("Nombre de mois") + ylab("proportion lissée (bleu)") + labs(title = paste("L'hypothèse nulle est vérifiée au mois ", firstAMLoessCIFUnder ), subtitle = "La valeur inférieure de l'intervalle de confiance de la courbe lissée \n passe sous la barre des 0.5", caption = paste("Proportion lissée de pages vues > 0 pour chaque distribution mensuelle \n niveau de confiance ", myAMCl)) ggsave(filename = "AM-PropPVsup1-Loess.jpg", dpi="print")
Restreignons l’investigation aux pages « Direct Marketing »
Comme nous l’avons indiqué précédemment, les pages « Direct Marketing » sont les pages visitées (Marketing ou non), uniquement suite à une entrée sur une page « Marketing ».
########################################################################## # Restreignons l'investigation aux pages "Direct Marketing" visitées uniquement # suite à une entrée sur une page "Marketing" (la même ou une autre) ########################################################################## str(myArticles) #verif #on garde uniquement les landingPagePath de nos articles : #DM = Direct Marketing patternArticlesToKeep <- unique(myArticles$pagePath) indexLandingPagePathToKeep <- grep(pattern = paste(patternArticlesToKeep, collapse="|"), dfPageViews$landingPagePath) dfDMPageViews <- dfPageViews[indexLandingPagePathToKeep,] str(dfDMPageViews) #28553 obs. #derniere date pour ce data.frame #pour récupéper des NAs plutot que des 0 par la suite. lastDMDate <- dfDMPageViews[nrow(dfDMPageViews),"date"] #Pour enregistrer les données du test dfDMPValue <- data.frame(pValue=double(), conf.int.inf = double(), conf.int.sup = double(), statistic = double(), myNotNas = double(), myNotNull = double(), myMedian = double()) myDMMd <- 0.01 #médiane de l'hypothèse nulle (0 ne marche pas ??? ) myDMCl <- 0.95 #niveau de confiance souhaité myLastMonth <- 90 #dernier mois à investiguer 7,5 années for (x in (1:myLastMonth)) { #pour enregistrer le nombre de pages vues de chaque article dans un mois dfDMThisMonthPV <- getMyDistribution(myPageViews=dfDMPageViews, myArticles=myArticles, myNumPeriode=x, myNbrOfDays=30, myLastDate=lastDMDate, myTestType="DM") #SIGN.test res <- SIGN.test(dfDMThisMonthPV$ThisPeriodPV, y=NULL, md=myDMMd, alternative="greater", conf.level = myDMCl) dfDMPValue[x, "pValue"] <- res$p.value dfDMPValue[x, "conf.int.inf"] <- res$conf.int[1] dfDMPValue[x, "conf.int.sup"] <- res$conf.int[2] dfDMPValue[x, "statistic"] <- res$statistic #taille de l'échantillon : dfDMPValue[x, "myNotNas"] <- sum(!is.na(dfDMThisMonthPV$ThisPeriodPV)) #nombre de valeurs > 0 #calculé à la main hors de SIGN.test pour le #calcul IC Proportion : dfDMPValue[x, "myNotNull"] <- sum(!(dfDMThisMonthPV[!is.na(dfDMThisMonthPV$ThisPeriodPV), "ThisPeriodPV"]==0)) dfDMPValue[x, "myMedian"] <- median(!is.na(dfDMThisMonthPV$ThisPeriodPV)) #médiane } #Visualisation de la p.valeur du SIGN.test myfirstMonthPValueUpper <- which.first(dfDMPValue$pValue > 0.05) ggplot(data=dfDMPValue, aes(x=as.numeric(row.names(dfDMPValue)), y=pValue)) + geom_line() + #, size=myNotNas geom_vline(xintercept= myfirstMonthPValueUpper, color="green") + geom_hline(yintercept = 0.05, color="red") + xlab("Nombre de mois") + ylab("P-Valeur") + labs(title = paste("L'hypothèse nulle est vérifiée dès le mois", myfirstMonthPValueUpper, "(ligne verte)" ), subtitle = "La ligne rouge indique la p Valeur à 0.05.", caption = paste("Direct MArketing - P.valeur SIGN.test médiane ", myDMMd, " niveau de confiance ", myDMCl)) #sauvegarde du dernier ggplot ggsave(filename = "DM-SIGN-Test-P-Value.jpg", dpi="print")
Remarque : Il reste 28553 observations.
Proportions lissées, comparatif ArtIcles Marketing et Direct Marketing
################################################################# ## Comparatifs AM MD . #Calcul Valeurs lissées pour Direct Marketing myDMLoess <- loess((myNotNull/myNotNas)~row.names(dfDMPValue), dfDMPValue ) myDMLoess$fitted #valeurs lissées #Première valeur lissée sous la barre des 0.5 i.e mediane = 0 firstDMLoessUnder <- which.first(myDMLoess$fitted <= 0.5) #le premier #borne inférieure # valeurs lissées inférieures myDMLoess$conf.int.inf <- myDMLoess$fitted - (myDMLoess$s/2) #Première valeur de la borne inférieure de l'IC lissée sous la #barre des 0.5 i.e mediane = 0 firstDMLoessCIFUnder <- which.first(myDMLoess$conf.int.inf <= 0.5) #comparatif du rapport entre les Dist > 0 / myNotnas pour AM # et MD ggplot() + geom_line(data=dfAMPValue, aes(x=as.numeric(row.names(dfAMPValue)), y=statistic/myNotNas), col="blue") + geom_smooth(data=dfAMPValue, aes(x=as.numeric(row.names(dfAMPValue)), y=statistic/myNotNas)) + geom_line(data=dfDMPValue, aes(x=as.numeric(row.names(dfDMPValue)), y=statistic/myNotNas), col = "red") + geom_smooth(data=dfDMPValue, aes(x=as.numeric(row.names(dfDMPValue)), y=statistic/myNotNas), col = "red") + geom_hline(yintercept = 0.5, color="red") + geom_vline(xintercept= firstDMLoessCIFUnder, color="green") + xlab("Nombre de mois") + ylab("proportion lissée - AM: bleu, DM : rouge ") + labs(title = paste("L'hypothèse nulle pour Direct Marketing est vérifiée au mois ", firstDMLoessCIFUnder ), subtitle = "La valeur inférieure de l'intervalle de confiance de la courbe lissée \n passe sous la barre des 0.5", caption = paste("Proportion lissée Articles Marketing et Direct Marketing \n de pages vues > 0 pour chaque distribution mensuelle \n niveau de confiance ", myAMCl)) ggsave(filename = "DM-AM-PropPVsup1-Loess.jpg", dpi="print")
Restreignons encore aux pages « Unique Marketing »
Il s’agit des pages « Marketing » visitées uniquement suite à une entrée sur la même page « Marketing ».
################################################################# # Restreignons encore l'investigation aux pages visitées # uniquement suite à une entrée sur la même page "Marketing" # UM : Unique Marketing ################################################################# str(myArticles) #verif #on garde uniquement les landingPagePath = pagePath dfUMPageViews <- dfDMPageViews[(as.character(dfDMPageViews$landingPagePath) == as.character(dfDMPageViews$pagePath)) ,] str(dfUMPageViews) #21214 obs. #derniere date pour ce data.frame lastUMDate <- dfUMPageViews[nrow(dfUMPageViews),"date"] #pour récupéper des NA plutot que des 0 par la suite. #Pour enregistrer les données du test dfUMPValue <- data.frame(pValue=double(), conf.int.inf = double(), conf.int.sup = double(), statistic = double(), myNotNas = double(), myNotNull = double(), myMedian = double()) myUMMd <- 0.01 #médiane de l'hypothèse nulle (0 ne marche pas ) myUMCl <- 0.95 #niveau de confiance souhaité myLastMonth <- 90 #dernier mois à investiguer 7,5 années ################################################################# for (x in (1:myLastMonth)) { #pour enregistrer le nombre de pages vues de chaque article #dans un mois dfUMThisMonthPV <- getMyDistribution(myPageViews=dfUMPageViews, myArticles=myArticles, myNumPeriode=x, myNbrOfDays=30, myLastDate=lastUMDate, myTestType="AM") #SIGN.test res <- SIGN.test(dfUMThisMonthPV$ThisPeriodPV, y=NULL, md=myUMMd, alternative="greater", conf.level = myUMCl) dfUMPValue[x, "pValue"] <- res$p.value dfUMPValue[x, "conf.int.inf"] <- res$conf.int[1] dfUMPValue[x, "conf.int.sup"] <- res$conf.int[2] dfUMPValue[x, "statistic"] <- res$statistic #taille de l'échantillon : dfUMPValue[x, "myNotNas"] <- sum(!is.na(dfUMThisMonthPV$ThisPeriodPV)) #nombre de valeurs > 0 : calculé à la main hors de SIGN.test #pour le calcul avec IC Proportion dfUMPValue[x, "myNotNull"] <- sum(!(dfUMThisMonthPV[!is.na(dfUMThisMonthPV$ThisPeriodPV), "ThisPeriodPV"]==0)) dfUMPValue[x, "myMedian"] <- median(!is.na(dfUMThisMonthPV$ThisPeriodPV)) #médiane } #Visualisation de la p.valeur du SIGN.test myfirstMonthPValueUpper <- which.first(dfUMPValue$pValue > 0.05) ggplot(data=dfUMPValue, aes(x=as.numeric(row.names(dfUMPValue)), y=pValue)) + geom_line() + #, size=myNotNas geom_vline(xintercept= myfirstMonthPValueUpper, color="green") + geom_hline(yintercept = 0.05, color="red") + xlab("Nombre de mois") + ylab("P-Valeur") + labs(title = paste("L'hypothèse nulle est vérifiée dès le mois", myfirstMonthPValueUpper, "(ligne verte)" ), subtitle = "La ligne rouge indique la p Valeur à 0.05.", caption = paste("Unique Marketing - P.valeur SIGN.test médiane ", myUMMd, " niveau de confiance ", myUMCl)) #sauvegarde du dernier ggplot ggsave(filename = "UM-SIGN-Test-P-Value.jpg", dpi="print")
il reste 21214 observations pour Unique Marketing.
Proportions lissées, comparatif ArtIcles Marketing, Direct Marketing ET UNIQUE MARKETING
################################################################# ## Comparatifs AM DM UM ################################################################# #Calcul Valeurs lissées pour Direct Marketing myUMLoess <- loess((myNotNull/myNotNas)~row.names(dfUMPValue), dfUMPValue ) str(myUMLoess) myUMLoess$fitted #valeurs lissées #Première valeur lissée sous la barre des 0.5 i.e mediane = 0 #le premier : firstUMLoessUnder <- which.first(myUMLoess$fitted <= 0.5) #borne inférieure : valeurs lissées inférieures myUMLoess$conf.int.inf <- myUMLoess$fitted - (myUMLoess$s/2) #Première valeur de la borne inférieure de l'IC lissée sous la barre #des 0.5 i.e mediane = 0 firstUMLoessCIFUnder <- which.first(myUMLoess$conf.int.inf <= 0.5) #comparatif du rapport entre les Dist > 0 / myNotnas pour AM, # MD et UM ggplot() + geom_line(data=dfAMPValue, aes(x=as.numeric(row.names(dfAMPValue)), y=statistic/myNotNas), col="blue") + geom_smooth(data=dfAMPValue, aes(x=as.numeric(row.names(dfAMPValue)), y=statistic/myNotNas)) + geom_line(data=dfDMPValue, aes(x=as.numeric(row.names(dfDMPValue)), y=statistic/myNotNas), col = "red") + geom_smooth(data=dfDMPValue, aes(x=as.numeric(row.names(dfDMPValue)), y=statistic/myNotNas), col = "red") + geom_line(data=dfUMPValue, aes(x=as.numeric(row.names(dfUMPValue)), y=statistic/myNotNas)) + geom_smooth(data=dfUMPValue, aes(x=as.numeric(row.names(dfUMPValue)), y=statistic/myNotNas), col = "black") + geom_hline(yintercept = 0.5, color="red") + geom_vline(xintercept= firstUMLoessCIFUnder, color="green") + xlab("Nombre de mois") + ylab("proportion lissée - AM : bleu, DM : rouge, UM : noir ") + labs(title = paste("L'hypothèse nulle pour Unique Marketing est vérifiée au mois ", firstUMLoessCIFUnder ), subtitle = "La valeur inférieure de l'intervalle de confiance de la courbe lissée \n passe sous la barre des 0.5", caption = paste("Proportion lissée Articles Marketing, Direct Marketing et Unique Marketing \n de pages vues > 0 pour chaque distribution mensuelle \n niveau de confiance ", myAMCl)) ggsave(filename = "UM-DM-AM-PropPVsup1-Loess.jpg", dpi="print")
Conclusion
Selon que l’on ait une vision restrictive des « Articles Marketing » ou que l’on utilise les données brutes ou les données lissées l’efficacité des Articles en terme de trafic supplémentaire varie de 7 mois à 21 mois.
Cette conclusion est valide juste pour le site étudié et les articles étudiés. Il serait intéressant de généraliser ce type d’études avec de nombreux sites et groupes de pages ou d’articles pour pouvoir faire des comparatifs intéressants.
Et vous qu’obtenez-vous comme résultats ?
A bientôt,
Pierre