Commit 440f3cd9 authored by Romain Creuzenet's avatar Romain Creuzenet

correction Orthographe

parent af286816
/__pycache__/*
*/__pycache__/*
/env_nf26/*
*.~lock.*
/out
/out/*
*.pyc
......@@ -3,8 +3,8 @@
<component name="ChangeListManager">
<list default="true" id="dec891dc-2fad-4291-af33-64d4fd64029d" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/diapo.odp" beforeDir="false" afterPath="$PROJECT_DIR$/diapo.odp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/livrables/Rapport-LATEX/main.tex" beforeDir="false" afterPath="$PROJECT_DIR$/livrables/Rapport-LATEX/main.tex" afterDir="false" />
<change beforePath="$PROJECT_DIR$/scripts/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/main.py" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
......@@ -15,19 +15,10 @@
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/create_table.py">
<entry file="file://$PROJECT_DIR$/scripts/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="912">
<caret line="51" column="17" selection-start-line="51" selection-start-column="17" selection-end-line="51" selection-end-column="17" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="184">
<caret line="62" column="54" lean-forward="true" selection-start-line="62" selection-start-column="54" selection-end-line="62" selection-end-column="54" />
<state relative-caret-position="-3152">
<caret line="243" column="66" selection-start-line="243" selection-start-column="66" selection-end-line="243" selection-end-column="66" />
<folding>
<element signature="e#45#107#0" expanded="true" />
</folding>
......@@ -36,20 +27,20 @@
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/download_data.py">
<entry file="file://$PROJECT_DIR$/scripts/create_table.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="95">
<caret line="5" column="52" selection-start-line="5" selection-start-column="52" selection-end-line="5" selection-end-column="52" />
<state>
<folding>
<element signature="e#0#64#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/parameters.py">
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/scripts/download_data.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="228">
<caret line="15" column="1" selection-start-line="15" selection-start-column="1" selection-end-line="15" selection-end-column="1" />
</state>
<state relative-caret-position="-804" />
</provider>
</entry>
</file>
......@@ -68,6 +59,7 @@
<find>service</find>
<find>figure</find>
<find>print</find>
<find>query3</find>
</findStrings>
<replaceStrings>
<replace>SESSION</replace>
......@@ -83,6 +75,7 @@
<option value="$PROJECT_DIR$/create_table.py" />
<option value="$PROJECT_DIR$/parameters.py" />
<option value="$PROJECT_DIR$/main.py" />
<option value="$PROJECT_DIR$/scripts/main.py" />
</list>
</option>
</component>
......@@ -100,7 +93,6 @@
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<expand>
......@@ -108,10 +100,16 @@
<item name="nf26_projet" type="b2602c69:ProjectViewProjectNode" />
<item name="nf26_projet" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="nf26_projet" type="b2602c69:ProjectViewProjectNode" />
<item name="nf26_projet" type="462c0819:PsiDirectoryNode" />
<item name="scripts" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
......@@ -252,13 +250,37 @@
</entry>
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="184">
<caret line="62" column="54" lean-forward="true" selection-start-line="62" selection-start-column="54" selection-end-line="62" selection-end-column="54" />
<state relative-caret-position="874">
<caret line="62" column="54" selection-start-line="62" selection-start-column="54" selection-end-line="62" selection-end-column="54" />
<folding>
<element signature="e#45#107#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/scripts/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-3152">
<caret line="243" column="66" selection-start-line="243" selection-start-column="66" selection-end-line="243" selection-end-column="66" />
<folding>
<element signature="e#45#107#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/scripts/create_table.py">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#64#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/scripts/download_data.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-804" />
</provider>
</entry>
</component>
</project>
\ No newline at end of file
......@@ -2,49 +2,54 @@
Authors : Lorys Hamadache et Romain Creuzenet
## Organisation générale du projet
- livrables : contient le rapport PDF et le Diapo PDF
- scripts : contient le code python concernant le projet
### ToDos
1. Verifier l'orthographe
2. Rendre le projet public
3. Confirmer les nouvelles versions rapports + code
4. Fichier Asos vs CSVs?
1. Verifier l'orthographe : Ok
2. Rendre le projet public :
3. Confirmer les nouvelles versions rapports + code: Romain : Ok
4. Fichier Asos vs CSVs? : Romain -> CSV
5. Envoyer au prof
## Comment utiliser le projet
Pour installer le projet :
- Pour installer le projet :
télécharcher toutes les librairies python listées dans requirements.txt
Pour initialiser les données (la première fois quand les tables sont vides):
1. Executer download_data.py qui va télécharger tous les fichiers CSV nécessaires
2. Executer create_table.py qui va créer et remplir les tables avec le contenu des fichiers CSV téléchargés
- Pour initialiser les données (la première fois quand les tables sont vides):
1. Executer download_data.py qui va télécharger tous les fichiers CSV nécessaires
2. Executer create_table.py qui va créer et remplir les tables avec le contenu des fichiers CSV téléchargés
Pour exploiter l'un des 3 objectif du projet:
- Pour exploiter l'un des 3 objectif du projet:
exécuter main.py. Une interface dans le terminal va vous guider
## Objectifs du projets
• Pour un point donné de l’espace, je veux pouvoir avoir un historique du passé, avec des courbes adaptés. Je vous pouvoir mettre en évidence la saisonnalité et les écarts à la saisonnalité.
• À un instant donné je veux pouvoir obtenir une carte me représentant n’importe quel indicateur.
- Pour un point donné de l’espace, je veux pouvoir avoir un historique du passé, avec des courbes adaptés. Je vous pouvoir mettre en évidence la saisonnalité et les écarts à la saisonnalité.
• Pour une période de temps donnée, je veux pouvoir obtenir clusteriser l’espace, et représenter cette clusterisation.
- À un instant donné je veux pouvoir obtenir une carte me représentant n’importe quel indicateur.
## Architecture du projet
• Le fichier « parameters.py » :
Il permet de stoker la configuration du projet (pays concerné, période de temps étudiée…). Il possède également les informations utiles à tout le projet.
- Pour une période de temps donnée, je veux pouvoir obtenir clusteriser l’espace, et représenter cette clusterisation.
• Le fichier « requierments.txt » :
## Architecture précise du projet
- Le fichier « requierments.txt » :
Ce fichier permet d’obtenir toutes les librairies à installer pour faire fonctionner le projet.
- livrables : contient le rapport PDF et le Diapo PDF
- scripts : contient le code python concernant le projet
- Le fichier « parameters.py » :
Il permet de stoker la configuration du projet (pays concerné, période de temps étudiée…). Il possède également les informations utiles à tout le projet.
Le fichier « download_data.py » :
- Le fichier « download_data.py » :
Ce fichier permet de télécharger les données du pays concerné sur la période temps étudiée depuis le site internet où elles sont stockées. Ces informations seront ensuite placées dans des fichiers « csv » par station dans le dossier « out ». Le code est inspiré de celui trouvé sur le site internet gardant les données. Ce fichier n’est utilisé que très rarement, à une initialisation. Il suffit de l’exécuter pour appeler les bonnes fonctions.
Le fichier « create_table.py » :
- Le fichier « create_table.py » :
Ce fichier crée les différentes tables utilisées durant le projet et les remplie des informations contenues dans tous les fichiers « csv » du dossier « out ». Ce fichier n’est utilisé que très rarement, à une initialisation. Il suffit de l’exécuter pour appeler les bonnes fonctions.
Le fichier « main.py » :
- Le fichier « main.py » :
Ce fichier gère l’exploitation des données. Il est utilisé fréquemment. Son exécution permet d’obtenir une interface dans le terminal pour choisir son objectif, les éléments nécessaires et obtenir les résultats.
• Le dossier « out » :
Ce dossier stocke les graphiques issues de l’exploitation des données. Les fichiers qu’il contient peuvent être consulté plus tard, par l’utilisateur
• Le dossier « data » :
- Le dossier « data » :
Ce dossier contient tous les fichiers « csv » contenant toutes les informations, sur les différentes stations, qui devront être mises dans Cassandra. Ce dossier n’est pas censé être exploité manuellement par l’utilisateur.
- Le dossier « imgs » :
Ce dossier contient toutes les images utilisées pour les rapports
......@@ -23,23 +23,23 @@ Le but de ce projet est de manipuler diverses données climatiques issues de plu
L'enjeu principal est le stockage pertinent des données dans nos bases de données NoSQL Cassandra et d’exploiter ces résultats avec le langage Python pour répondre à plusieurs objectifs. Notre code se doit d'être adapté à une forte quantité de données.
\section{Stockage des données}
\emph{Le stockage des données est la partie la plus importante lors de la réalisation d'un tel outil d'analyse. C'est pourquoi on s'intéresse ici aux données et objectifs de notre outils afin de réaliser un stockage adapté. }
\emph{Le stockage des données est la partie la plus importante lors de la réalisation d'un tel outil d'analyse. C'est pourquoi on s'intéresse ici aux données et objectifs de notre outil afin de réaliser un stockage adapté. }
\subsection{Les données}
Nous nous intéressons ici au cas de l'Espagne. L'Espagne consiste en 62 stations réparties sur tout le territoire Espagnol continental en passant par les Îles Canaries et les Îles Baléares. Nos données contiennent 30 variables comme la température ou l'humidité. Les données sont téléchargeables en 1 seul fichier où chaque ligne représente une mesure avec sa station, les cordonnées de celle ci (lat,lon), la date de la mesure (Précision : Minute) et les mesures des différentes variables. Nous avons pour la période choisie (2011 - 2013) environ 1.5M d'entrées. On remarque aussi que nous avons des variables toujours nulles, ainsi que de nombreuses variables souvent nulles. \newline
Nous nous intéressons ici au cas de l'Espagne. L'Espagne consiste en 62 stations réparties sur tout le territoire espagnol continental en passant par les Îles Canaries et les Îles Baléares. Nos données contiennent 30 variables comme la température ou l'humidité. Les données sont téléchargeables en un seul fichier où chaque ligne représente une mesure avec sa station, les cordonnées de celle-ci (lat, lon), la date de la mesure (Précision : Minute) et les mesures des différentes variables. Nous avons pour la période choisie (2011 - 2013) environ 1.5 M d'entrées. On remarque aussi que nous avons des variables toujours nulles, ainsi que de nombreuses variables souvent nulles. \newline
Nous utilisons un stockage en colonne à l'aide de Cassandra mis à notre disposition sur 3 clusters. Notre système soit d'être toujours opérationnel même lors de l'absence des certaines parties et toujours nous retourner une valeur. C'est aussi un modèle qui nous permet de manipuler plus facilement toutes nos variables incomplètes et les colonnes presque nulles ne prennent pas trop d'espace.\newline
Nous utilisons un stockage en colonne à l'aide de Cassandra mis à notre disposition sur 3 clusters. Notre système se doit d'être toujours opérationnel même lors de l'absence des certaines parties et toujours nous retourner une valeur. C'est aussi un modèle qui nous permet de manipuler plus facilement toutes nos variables incomplètes et les colonnes presque nulles ne prennent pas trop d'espace.\newline
Nous utilisons seulement ces données la pour des questions de temps d'importation et de test. Il est plus simple de tester sur une quantité raisonnable de données pour ensuite porter le code en version finale avec toutes les données (2001 - 2019).
Nous utilisons seulement ces données-ci pour des questions de temps d'importation et de test. Il est plus simple de tester sur une quantité raisonnable de données pour ensuite porter le code en version finale avec toutes les données (2001 - 2019).
\subsection{Les Tables et nos objectifs}
\emph{Objectif 1 :Pour un point donné de l’espace, je veux pouvoir avoir un historique du passé, avec des courbes adaptés. Je vous pouvoir mettre en évidence la saisonnalité et les écarts à la saisonnalité.} \newline
Le premier objectif est, pour un point donné, autrement dit, pour l’une des stations espagnoles, d’obtenir un historique des données d’un attribut (par exemple l’humidité). On souhaite afficher et stocker des courbes expliquant l'évolution d'un attribut et sa saisonnalité. Comment stocker nos données afin de pouvoir les exploiter au mieux?\newline
Le premier objectif est, pour un point donné, autrement dit, pour l’une des stations espagnoles, d’obtenir un historique des données d’un attribut (par exemple l’humidité). On souhaite afficher et stocker des courbes expliquant l'évolution d'un attribut et sa saisonnalité. Comment stocker nos données afin de pouvoir les exploiter au mieux ?\newline
Pour notre table, appelée TABLE\_SPACE, nous avons donc utilisé comme clef de partition la station, permettant ainsi d’obtenir l’ensemble de ses mesures et pouvoir faire l’historique de chacun. Pour différencier chacune de ces mesures, nous nous sommes servi de la date de celles-ci en clef de tri (année, mois, jour, minute, heure). \newline
Pour notre table, appelée TABLE\_SPACE, nous avons donc utilisé comme clef de partition la station, permettant ainsi d’obtenir l’ensemble de ses mesures et de pouvoir en faire un historique. Pour différencier chacune de ces mesures, nous nous sommes servi de la date de celles-ci en clef de tri (année, mois, jour, minute, heure). \newline
Dans notre exploitation, nous choisissons une station puis un seul attribut (pour plus de clarté) et que, dans ce cas, la possibilité d’utiliser l’attribut comme clef de partition, la date comme clef de tri et y associer l’ensemble des mesures de chaque station est possible. Or, si suite à une évolution, nous voulons faire, en une fois, l’historique de tous les attributs d’une station cela n’est plus possible, d’où notre choix. De plus, nous stockons des informations non-essentielles comme la longitude ou la latitude. Cela est fait dans le cas d’une autre exploitation de la base.\newline
......@@ -51,14 +51,14 @@ Le second objectif fut d’obtenir, à un instant donné, une carte affichant le
L’objectif 3 consiste à effectuer une clusterisation des différentes stations par rapport aux données météorologiques sur une période de temps demandée. Nous faisons une moyenne de chaque attribut de chaque station sur la période étudiée, en récoltant les données en streaming.\newline
Pour effectuer cet objectif, la table de l’objectif 2 a été reprise, car sa clef de partition est le temps. Une itération de requête est effectuée avec une date précise, en étant incrémentée de la plus petite unité de mesure : la minute. Nous aurions pu créer une nouvelle table partitionnée à l’heur ou au jour, mais avons choisi de garder la même table pour un souci de volume de donnée et en préconisant des périodes courtes. Un nouveau partitionnement aurait suivi les mêmes principes.\newline
Pour effectuer cet objectif, la table de l’objectif 2 a été reprise, car sa clef de partition est le temps. Une itération de requête est effectuée avec une date précise, en étant incrémentée de la plus petite unité de mesure : la minute. Nous aurions pu créer une nouvelle table partitionnée à l’heur ou au jour, mais avons choisi de garder la même table pour un souci de volume de données et en préconisant des périodes courtes. Un nouveau partitionnement aurait suivi les mêmes principes.\newline
\section{Notre outil et le traitement des données}
Dans cette partie nous allons voir en détail comment nous avons réaliser un outil permettant de répondre aux 3 objectifs et les traitements associés afin de gérer la quantité de données potentielle.
Dans cette partie nous allons voir en détail comment nous avons réalisé un outil permettant de répondre aux 3 objectifs et les traitements associés afin de gérer la quantité de données potentielle.
\subsection{Interface}
Nous avons choisi de réaliser une interface simple textuel en Python. Nous affichons du texte à l'utilisateur et celui ci peut saisir ses choix. Lorsque l'on lance notre programme, à partir de la commande {\tt >> python3 main.py}. Il est nécessaire de charger l'environnement Spark au préalable ({\tt source /pyspark.env}).
Nous avons choisi de réaliser une interface simple textuel en Python. Lorsque le programme est executé (avec {\tt >> python3 main.py}), du texte est affiché à l'utilisateur et ce dernier peut alors intéragir. Il est nécessaire de charger l'environnement Spark au préalable ({\tt source /pyspark.env}).
On se retrouve sur l'interface suivante où l'utilisateur peut faire un choix:
\begin{figure}[H]
......@@ -71,10 +71,10 @@ On se retrouve sur l'interface suivante où l'utilisateur peut faire un choix:
\subsection{Objectif 1}
Pour réaliser l'objectif 1 nous avons réaliser la fonction {\tt historic}. Comment gérons nous la quantité de donnée dont nous avons besoin? Dans un premier temps, la fonction est un prolongement de la partie interface. On demande à l'utilisateur de choisir la station sur laquelle il veut obtenir les courbes. Pour cela, on affiche toutes les stations ayant des données à l'aide d'une requête à la table TABLE\_SPACE de notre base Cassandra où nous sélectionnons les stations distincts. Il y a peu de stockage dans ce cas là donc pas de problème à ce niveau la. Ensuite on demande à l'utilisateur quel indicateur il souhaite visionner (température, humidité ...).\newline
Pour réaliser l'objectif 1 nous avons créé la fonction {\tt historic}. Comment gérons-nous la quantité de donnée dont nous avons besoin ? Dans un premier temps, la fonction est un prolongement de la partie interface. On demande à l'utilisateur de choisir la station sur laquelle il veut obtenir les courbes. Pour cela, on affiche toutes les stations ayant des données à l'aide d'une requête à la table TABLE\_SPACE de notre base Cassandra où nous sélectionnons les stations distinctes. Il y a peu de stockage dans ce cas présent donc aucun problème concernant ce niveau. Puis, on demande à l'utilisateur quel indicateur il souhaite visionner (température, humidité ...).\newline
On arrive à la partie intéressante. Comment gérer le nombre important de données de la station? Dans un premier temps on ne réalise la requête que sur ce que nous avons besoin, c'est à dire la date et la valeur de l'attribut.
Notre requête nous retourne un générateur. Mais celui ci peut contenir beaucoup trop de données. En effet nous avons quelques fois plusieurs mesures par heure, pendant plusieurs années. Il est donc impossible de stocker tout cela. Nous décidons d'utiliser Spark afin de paralléliser nos traitement et réaliser des mappings et reductions successifs. Nous mappons et réduisons nos données en ne gardant que la le maximum, le minimum et la moyenne de l'attribut sur la journée. Ces traitements sont réaliser à la suite (max puis min puis avg). Lorsque la quantité de données sera trop importante on pourra passer à une réduction par semaine ou par mois. Ces données, fortement réduite sont mainenant stocker dans une Time Series grâce à la bibliothèque {\tt pandas}. Nous affichons ensuite sur un même graphique le maximum, le minimum et la moyenne de l'indicateur au cours du temps sur cette station. On réalise une interpolation sur les données pour les jours manquants.\newline
Comment gérer le nombre important de données de la station ? Dans un premier temps on ne réalise la requête que sur ce que nous avons besoin, c'est-à-dire, la date et la valeur de l'attribut.
Notre requête nous retourne un générateur. Mais celui-ci peut contenir trop de données. En effet, nous avons quelques fois plusieurs mesures par heure, pendant plusieurs années. Il est donc impossible de stocker tout cela. Nous décidons d'utiliser Spark afin de paralléliser nos traitements et réaliser des mappings et des reductions successifs. Nous mappons et réduisons nos données en ne gardant que le maximum, le minimum et la moyenne de l'attribut sur la journée. Ces traitements sont réalisés à la suite (max puis min puis avg). Lorsque la quantité de données sera trop importante on pourra passer à une réduction par semaine ou par mois. Ces données, fortement réduites sont maintenant stockées dans une Time Series grâce à la bibliothèque {\tt pandas}. Nous affichons ensuite sur un même graphique le maximum, le minimum et la moyenne de l'indicateur au cours du temps de cette station. On réalise une interpolation sur les données pour les jours manquants.\newline
\begin{figure}[H]
\begin{center}
......@@ -83,7 +83,7 @@ Notre requête nous retourne un générateur. Mais celui ci peut contenir beauco
\end{center}
\end{figure}
Avec la bibliothèque {\tt statsmodels}, on en profite pour réaliser un graphique d'autocorrelation ainsi qu'une décomposition de notre time series en une composante de tendance, une composante saisonnal et les résidus. Cela nous permet de répondre entièrement à la question en étudiant la saisonnalité du signal ainsi que les résidus hors tendance et saisons. On peut voir sur la décomposition une tendance à la baisse de la température et clairement un rythme saisonnier par année.
Avec la bibliothèque {\tt statsmodels}, on en profite pour réaliser un graphique d'autocorrelation ainsi qu'une décomposition de notre time series en une composante de tendance, une composante saisonnale et les résidus. Cela nous permet de répondre entièrement à la question en étudiant la saisonnalité du signal ainsi que les résidus hors tendance et saisons. On peut voir sur la décomposition une tendance à la baisse de la température et clairement un rythme saisonnier par année.
\begin{figure}[H]
\begin{center}
......@@ -102,8 +102,8 @@ Avec la bibliothèque {\tt statsmodels}, on en profite pour réaliser un graphiq
\subsection{Objectif 2}
Dans un premier temps on demande une date et une heure et un attribut à l'utilisateur de la même façon que précedemment. Si la date n'existe pas, on lui affiche les heures disponibles avec des mesures dans le jour qu'il a demandé.
Pour cet objectif, nous n'avons pas de problème de données. En effet grâce à notre deuxième table (TABLE\_TIME) nous pouvons faire une requête, à un temps et un attribut donnés. La quantité de données est égale au nombre de stations *4 (Nom de la station, longitude et latitude de la station et valeur de l'attribut).Ensuite nous utilisons la bibliothèque {\tt mpl\_toolkits.basemap} pour afficher une carte de l'Espagne sur laquelle on trace les stations (des points) et auquel on annote à coté la valeur de l'attribut à cet emplacement. Cela nous permet de visualiser rapidement un indicateur à travers l'espace.
Dans un premier temps on demande une date et une heure et un attribut à l'utilisateur de la même façon que précédemment. Si la date n'existe pas, on lui affiche les heures disponibles avec des mesures dans le jour qu'il a demandé.
Pour cet objectif, nous n'avons pas de problème de données. En effet, grâce à notre deuxième table (TABLE\_TIME) nous pouvons faire une requête, à un temps et à un attribut donnés. La quantité de données est égale au nombre de stations multiplié par 4 (Nom de la station, longitude et latitude et valeur de l'attribut). Ensuite nous utilisons la bibliothèque {\tt mpl\_toolkits.basemap} pour afficher une carte de l'Espagne sur laquelle on place les stations (des points) et auquelmes la valeur de l'attribut est annotée. Cela permet de visualiser rapidement un indicateur à travers l'espace.
\begin{figure}[H]
\begin{center}
......@@ -114,9 +114,9 @@ Pour cet objectif, nous n'avons pas de problème de données. En effet grâce à
\subsection{Objectif 3}
En premier lieu, nous demandons à l'utilisateur la période sur laquelle il veut réaliser sa clusturisation. Après avoir obtenu le générateur de toutes les données sur cette période, on ne peut pas les stocker de cette façons pour raison évidente de coût mémoire, en particulier si la période est longue et que le nombre de données augmente. Pour cela, on calcule la moyenne par station de tous les attributs sur la période données, tout cela réalisé en "streaming" pour ne pas avoir de problème de mémoire.\newline
En premier lieu, nous demandons à l'utilisateur la période sur laquelle il veut réaliser sa clusturisation. Après avoir obtenu le générateur de toutes les données sur cette période, on ne peut pas les stocker de cette façon pour raison évidente de coût mémoire, en particulier si la période est longue et que le nombre de données augmente. Pour cela, on calcule la moyenne par station de tous les attributs sur la période donnée, tout cela est réalisé en "streaming" pour ne pas avoir de problème de mémoire.\newline
Le nombre de cluster souhaité est ensuite demandé à l’utilisateur. On réalise un algorithme des kmeans à la main. On pourrait paralléliser les calculs si nécéssaires. Pour clusteriser, dans un premier temps, nous générons les centroÏdes avec des valeurs aléatoires comprises entre le minimum et le maximum des moyennes recueillies pour chaque attribut. Nous clusterisons donc sur N dimensions, N étant le nombre d’attributs. La norme des vecteurs obtenus est comparée à celle de chaque station. De nouveaux centroïdes sont calculés par rapport à la moyenne des stations dont la norme de leur vecteur est la plus proche. Cette opération est effectuée jusqu’à une stabilisation des centroïdes. Si les centroïdes n’ont aucun station associée, les centroïdes sont renouvelées aléatoirement.
Le nombre de cluster souhaité est ensuite demandé à l’utilisateur. On réalise un algorithme des kmeans à la main. On pourrait paralléliser les calculs si nécessaire. Pour clusteriser, dans un premier temps, nous générons les centroÏdes avec des valeurs aléatoires comprises entre le minimum et le maximum des moyennes recueillies pour chaque attribut. Nous clusterisons donc sur N dimensions, N étant le nombre d’attributs. La norme des vecteurs obtenus est comparée à celle de chaque station. De nouveaux centroïdes sont calculés par rapport à la moyenne des stations dont la norme de leur vecteur est la plus proche. Cette opération est effectuée jusqu’à une stabilisation des centroïdes. Si les centroïdes n’ont aucune station associée, les centroïdes sont renouvelées aléatoirement.
Une fois clusterisé, les stations sont affichées sur la carte comme dans l’objectif précédent. Leur appartenance à un cluster est visible par la couleur affichée. Sur l'exemple, on remarque qu'avec 3 clusters, quelques groupes logiques se dessinent. Nous avons en vert des stations côtières et en rouge des stations dans les terres.
......@@ -145,7 +145,7 @@ Ce dossier contient tous les fichiers contenant nos données qui devront être m
\section{Conclusion}
Ce projet est un projet intéressant pour se confronter à des données réelles. Cela nous permet de comprendre et de mettre en pratique nos connaissances sur les bases de données orientées colonnes. C'est en se posant des questions sur les données et en ne perdant pas de vues l'objectif final de pouvoir traiter énormément de données que l'on pense à réaliser un traitement de données en "streaming" et à réaliser du mapping et de la réduction. Pour aller plus loin que le "nec plus ultra" espagnol, on pourrait penser à paralléliser l'algorithme des kmeans ou utiliser la fonction existante dans Spark. De plus il serait intéressant d'étudier la performance en fonction du nombre de clusters et de répliquas utilisés. \newline
Ce projet est un projet intéressant pour se confronter à des données réelles. Cela nous permet de comprendre et de mettre en pratique nos connaissances sur les bases de données orientées colonnes. C'est en se posant des questions sur les données et en ne perdant pas de vu l'objectif final (pouvoir traiter énormément de données) que nous pensons à réaliser un traitement de données en "streaming" et à réaliser du mapping et de la réduction. Pour aller plus loin, on pourrait penser à paralléliser l'algorithme des kmeans ou utiliser la fonction existante dans Spark. De plus il serait intéressant d'étudier la performance en fonction du nombre de clusters et de répliquas utilisés. \newline
Vous trouverez le code complet à cette adresse : \href{https://gitlab.utc.fr/rcreuzen/nf26_projet/}{https://gitlab.utc.fr/rcreuzen/nf26\_projet/}\newline
......@@ -153,4 +153,4 @@ Vous trouverez le code complet à cette adresse : \href{https://gitlab.utc.fr/rc
{\Large Merci pour votre lecture}
\end{center}
\end{document}
\ No newline at end of file
\end{document}
......@@ -8,7 +8,7 @@ import warnings
import re
import os
import random
#parallelize
# parallelize
from pyspark import SparkContext
# Stats
import statsmodels.graphics as stm_graphs
......@@ -147,7 +147,6 @@ class Manager:
station = ask_q(stations)
attr = chose_attr()
# Base
ts = pd.Series()
query = "SELECT time, {} FROM {} WHERE station={}".format(attr, self.table, station.__repr__())
......@@ -169,55 +168,71 @@ class Manager:
plt.savefig(path)
plt.show()
#Initialisation SPARK
# Initialisation SPARK
sc = SparkContext()
#INITIALISATION BY DAY
# INITIALISATION BY DAY
plt.figure(figsize=(25, 16))
axes = plt.subplot()
axes.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
plt.xticks(rotation=90)
date_rng = pd.date_range(start='2011-01-01', end='2013-12-31', freq='D')
# Maximum of the Day
ts_max = pd.Series(index = date_rng)
query = "SELECT time, {} FROM {} WHERE station={}".format(attr, self.table, station.__repr__())
# Maximum of the Day
ts_max = pd.Series(index=date_rng)
gen_max = sc.parallelize(execute_query(query))
gen_max = gen_max.map(lambda line: ((getattr(line,"time")[0],getattr(line,"time")[1],getattr(line,"time")[2]), getattr(line,attr))).reduceByKey(lambda x,y: max(x,y)).collect()
gen_max = gen_max.map(lambda line: (
(
getattr(line, "time")[0],
getattr(line, "time")[1],
getattr(line, "time")[2]
),
getattr(line, attr)
)).reduceByKey(lambda x, y: max(x, y)).collect()
for a,b in gen_max:
for a, b in gen_max:
ts_max.loc[datetime(*list(a))] = b
ts_max = ts_max.sort_index()
ts_max = ts_max.interpolate()
plt.plot(ts_max , label="Maximum")
plt.plot(ts_max, label="Maximum")
# Minimum of the Day
ts_min = pd.Series(index = date_rng)
query2 = "SELECT time, {} FROM {} WHERE station={}".format(attr, self.table, station.__repr__())
gen_min = sc.parallelize(execute_query(query2))
gen_min = gen_min.map(lambda line: ((getattr(line,"time")[0],getattr(line,"time")[1],getattr(line,"time")[2]), getattr(line,attr))).reduceByKey(lambda x,y: min(x,y)).collect()
ts_min = pd.Series(index=date_rng)
gen_min = sc.parallelize(execute_query(query))
gen_min = gen_min.map(lambda line: (
(
getattr(line, "time")[0],
getattr(line, "time")[1],
getattr(line, "time")[2]
),
getattr(line, attr)
)).reduceByKey(lambda x, y: min(x, y)).collect()
for a,b in gen_min:
for a, b in gen_min:
ts_min.loc[datetime(*list(a))] = b
ts_min = ts_min.sort_index()
ts_min = ts_min.interpolate()
plt.plot(ts_min , label="Minimum")
plt.plot(ts_min, label="Minimum")
# Average of the Day
ts_avg = pd.Series(index = date_rng)
query3 = "SELECT time, {} FROM {} WHERE station={}".format(attr, self.table, station.__repr__())
gen_avg = sc.parallelize(execute_query(query2))
gen_avg = gen_avg.map(lambda line: ((getattr(line,"time")[0],getattr(line,"time")[1],getattr(line,"time")[2]), (getattr(line,attr),1))).reduceByKey(lambda x,y: (x[0] +y[0], x[1]+ y[1])).map(lambda x: (x[0],x[1][0]/x[1][1])).collect()
for a,b in gen_avg:
ts_avg = pd.Series(index=date_rng)
gen_avg = sc.parallelize(execute_query(query))
gen_avg = gen_avg.map(lambda line: (
(
getattr(line, "time")[0],
getattr(line, "time")[1],
getattr(line, "time")[2]
),
(getattr(line, attr), 1)
)).reduceByKey(lambda x, y: (x[0] + y[0], x[1] + y[1])).map(lambda x: (x[0], x[1][0]/x[1][1])).collect()
for a, b in gen_avg:
ts_avg.loc[datetime(*list(a))] = b
ts_avg = ts_avg.sort_index()
ts_avg = ts_avg.interpolate()
plt.plot(ts_avg , label="Moyenne")
plt.plot(ts_avg, label="Moyenne")
# Global Plotting
plt.title("Donnees de {} pour la station : {}".format(attr, station))
......@@ -226,7 +241,7 @@ class Manager:
plt.savefig(path)
plt.show()
res = stm.tsa.seasonal_decompose(ts_avg.dropna(), freq=365 , extrapolate_trend='freq')
res = stm.tsa.seasonal_decompose(ts_avg.dropna(), freq=365, extrapolate_trend='freq')
res.plot()
path = os.path.join(DIR_OUT, 'decompose_{}_{}.png'.format(station, attr))
plt.savefig(path)
......@@ -236,8 +251,6 @@ class Manager:
path = os.path.join(DIR_OUT, 'acf_{}_{}.png'.format(station, attr))
plt.savefig(path)
plt.show()
def map(self):
self.table = "TABLE_TIME"
......
......@@ -27,9 +27,9 @@ for key in KEY_SPACE:
if SESSION is None:
raise NoHostAvailable("Erreur de connection à cassandra", None)
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # path of project
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # path of project
DIR_DATA = os.path.join(BASE_DIR, "data") # folder with all data station
DIR_OUT = os.path.join(BASE_DIR, "out") # folder with all data station
DIR_OUT = os.path.join(BASE_DIR, "out") # folder with all graphics
NETWORK = "ES__ASOS" # Change
START = datetime.datetime(2011, 1, 1) # 1 janvier 2001
END = datetime.datetime(2013, 12, 31) # 31 décembre 2010
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment