-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDetectSignificantWebTrafficPython.py
More file actions
153 lines (134 loc) · 7.29 KB
/
DetectSignificantWebTrafficPython.py
File metadata and controls
153 lines (134 loc) · 7.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# -*- coding: utf-8 -*-
"""
Created on Tue May 23 10:50:38 2019
@author: Pierre
"""
#########################################################################
# DetectSignificatnWebTrafficPython
# Détection de trafic Web significatif avec Python
# Auteur : Pierre Rouarch 2019
# Données : Issues de l'API de Google Analytics -
# Comme illustration Nous allons travailler sur les données du site
# https://www.networking-morbihan.com
# Site de l'association Networking Morbihan :
# https://github.com/Anakeyn/DetectSignificantWebTrafficPython/raw/master/dfPageViews.zip
#.
#############################################################
# On démarre ici !!!!
#############################################################
#def main(): #on ne va pas utiliser le main car on reste dans Spyder
#Chargement des bibliothèques utiles
import numpy as np #pour les vecteurs et tableaux notamment
import matplotlib.pyplot as plt #pour les graphiques
import scipy as sp #pour l'analyse statistique
import pandas as pd #pour les Dataframes ou tableaux de données
import seaborn as sns #graphiques étendues
import math #notamment pour sqrt()
from datetime import timedelta
from scipy import stats
#pip install scikit-misc #pas d'install conda ???
from skmisc import loess #pour methode Loess compatible avec stat_smooth
#conda install -c conda-forge plotnine
from plotnine import * #pour ggplot like
#conda install -c conda-forge mizani
from mizani.breaks import date_breaks #pour personnaliser les dates affichées
#Changement du répertoire par défaut pour mettre les fichiers de sauvegarde
#dans le même répertoire que le script.
import os
print(os.getcwd()) #verif
#mon répertoire sur ma machine - nécessaire quand on fait tourner le programme
#par morceaux dans Spyder.
#myPath = "C:/Users/Pierre/CHEMIN"
#os.chdir(myPath) #modification du path
#print(os.getcwd()) #verif
###############################################################################
#Récupération du fichier de données
###############################################################################
myDateToParse = ['date'] #pour parser la variable date en datetime sinon object
dfPageViews = pd.read_csv("dfPageViews.csv", sep=";", dtype={'Année':object}, parse_dates=myDateToParse)
#verifs
dfPageViews.dtypes
dfPageViews.count() #72821 enregistrements
dfPageViews.head(20)
##############################################################################
#creation de la dataframe daily_data par jour
dfDatePV = dfPageViews[['date', 'pageviews']].copy() #nouveau dataframe avec que la date et le nombre de pages vues
daily_data = dfDatePV.groupby(dfDatePV['date']).count() #
#dans l'opération précédente la date est partie dans l'index
daily_data['date'] = daily_data.index #recrée la colonne date.
daily_data['cnt_ma30'] = daily_data['pageviews'].rolling(window=30).mean()
daily_data['Année'] = daily_data['date'].astype(str).str[:4]
daily_data['DayOfYear'] = daily_data['date'].dt.dayofyear #récupère la date du jour
daily_data.reset_index(inplace=True, drop=True) #on reindexe
#Graphique Moyenne Mobile 30 jours.
sns.set() #paramètres esthétiques ressemble à ggplot par défaut.
fig, ax = plt.subplots() #un seul plot
sns.lineplot(x='DayOfYear', y='cnt_ma30', hue='Année', data= daily_data,
palette=sns.color_palette("husl",n_colors=8))
fig.suptitle("Les données présentent une saisonnalité : ", fontsize=14, fontweight='bold')
ax.set(xlabel="Numéro de Jour dans l'année", ylabel='Nbre pages vues / jour en moyenne mobile',
title="Le trafic baisse en général en été.")
fig.text(.9,-.05,"Comparatif Nbre pages vues par jour par an moy. mob. 30 jours \n Données nettoyées",
fontsize=9, ha="right")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
#plt.show()
fig.savefig("PV-Comparatif-mm30.png", bbox_inches="tight", dpi=600)
# Sauvegarde de DailyData en csv pourra servir dans d'autres articles.
daily_data.to_csv("DailyDataCleanPython.csv", sep=";", index=False) #séparateur ;
##########################################################################
# Détection des événements significatifs - Données_aberrantes
# on va utiliser la méthode du Test de Tau de Thomson Modifié
# Voir ici https://fr.wikipedia.org/wiki/Donn%C3%A9e_aberrante
##########################################################################
#Etape 1 Calcul du Seuil
n=daily_data.shape[0] #taille de l'échantilon 2658
#Récupérons la valeur de Tau sur la table comme nous avons n = 2658
#notre valeur de tau est 1,96
tau=1.96
#calculons le seuil de base
threshold = (tau*(n-1))/( math.sqrt(n) * math.sqrt(n-2+(math.pow(tau,2))) )
#threshold=1.9585842166773806
#Etape 2 Evaluation du zcore par rapport au seuil
# ici z_score = (daily_data['pageviews'] - mean)/std donné
# par zcore de scipy.stats mais que l'on aurait pu calculer. à la main
from scipy.stats import zscore
daily_data['pageviews_zscore'] = zscore(daily_data['pageviews'])
myOutliersBase = daily_data[daily_data['pageviews_zscore'] > threshold]
len(myOutliersBase) #136 valeurs aberrantes
#Finalement on va augmenter le seuil de façon empirique pour réduire le
#nombre de valeurs aberrantes à un même niveau de ce que l'on avait avec R
threshold = 2.29
myOutliers = daily_data[daily_data['pageviews_zscore'] > threshold]
len(myOutliers) #97 valeurs
#Graphique Pages vues
sns.set() #paramètres esthétiques ressemble à ggplot par défaut.
fig, ax = plt.subplots() #un seul plot
sns.lineplot(x='date', y='pageviews', data= daily_data)
sns.scatterplot(x='date', y='pageviews', data= myOutliers, color='red')
fig.suptitle( str(len(myOutliers)) + " événements ont été détectés : ", fontsize=14, fontweight='bold')
ax.set(xlabel="Date", ylabel='Nbre pages vues / jour',
title="Il y a moins d'événements significatifs les dernières années")
fig.text(.9,-.05,"Evénements significatifs depuis 2011 détectés par calcul des valeurs aberrantes",
fontsize=9, ha="right")
#plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
#plt.show()
fig.savefig("Anoms-Pageviews-s2011.png", bbox_inches="tight", dpi=600)
#Affichage sur la courbe des moyennes mobiles sur 30 jours
sns.set() #paramètres esthétiques ressemble à ggplot par défaut.
fig, ax = plt.subplots() #un seul plot
sns.lineplot(x='date', y='cnt_ma30', data= daily_data)
sns.scatterplot(x='date', y='cnt_ma30', data= myOutliers, color='red')
fig.suptitle( str(len(myOutliers)) + " événements ont été détectés : ", fontsize=14, fontweight='bold')
ax.set(xlabel="Date", ylabel='Nbre pages vues en moyenne mobile / jour',
title="Il y a moins d'événements significatifs les dernières années")
fig.text(.9,-.05,"Evénements significatifs depuis 2011 détectés par calcul des valeurs aberrantes\n moyenne mobile 30 jours",
fontsize=9, ha="right")
#plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
#plt.show()
fig.savefig("Anoms-Pageviews-s2011-mm30.png", bbox_inches="tight", dpi=600)
##########################################################################
# MERCI pour votre attention !
##########################################################################
#on reste dans l'IDE
#if __name__ == '__main__':
# main()