Protocole de formatage des données pour l'interface

Ce protocole permet de formater vos données au format csv selon le protocole exigé par l'interface. Nous supposons que l'information temporelle (dates et heures) se situent dans une seule cellule. L'heure n'est pas indispensable.

Vous devrez saisir les codes des 3 étapes ci-dessous dans un script ou console R : lecture, alignement, création. Vous pouvez utiliser le carré à droite du code ("copy to clipboard"). L'étape 2 d'alignement dépend de votre souhait d'échantillonnage, nous vous donnons quelques exemples : de 10 minutes, 20 minutes, 30 minutes, 1 jour, 1 semaine, 1 mois...

Pour plus d'explications sur les lignes de codes, voir le protocole avec l'exemple MAREL-Carnot (Exemple MAREL-Carnot).

Lecture du fichier

Définir son répertoire de travail (dossier dans lequel se trouve les données brutes) et les informations associés à vos données, nom du fichier, format des dates dans ce fichier, nom de la colonne contenant les dates, ...

Veuillez renseigner les "à remplir"

rm(list=ls(all=TRUE))
graphics.off()
repDonnees="A remplir"  #ex sous linux :~/Protocole_uHMM/MAREL-Carnot" 
setwd(repDonnees)
nomfichier="A remplir" #nom Fichier ex MarelCarnot.csv 
nomDate="A remplir" # nom de la colonne de l'information temporelle

# format de votre colonne d=jour, m=mois,y=année en 2 chiffres Y pour 4
formatDate="A remplir " # ex %d/%m/%y %H:%M:%S" 
separateur="," # à changer au besoin
decimale="." # à changer au besoin

#lecture du fichier
df=read.csv(nomfichier,header=T,sep=separateur, dec=decimale)
dim(df) # visualisation du nb observations et de colonnes
names(df) # Visualisation des noms de toutes les colonnes de df.

#formatage du temps au format machine POSIXct
idate=grep(pattern=nomDate, names(df),ignore.case=T)
date=as.character((df)[,idate])
df$temps=strptime(date, format=formatDate)

Noter que la date est extraite puis mise sous le format POSIXt (AAAA-MM-JJ hh:mm:ss). L'argument "format" reprend exactement le format initial de la colonne date.
%Y correspond aux années décrites par 4 chiffres comme 2017 sinon %y pour 17
%m correspond au mois
%d correpond au jour
%H correspond à l'heure
%M correspond aux minutes
%S correspond aux secondes

Alignements

Le but de cet étape est de rendre régulière la série. Tout capteur sera synchronisé sur un pas unique (règle du max si le capteur répond deux fois dans le même intervalle). De plus, si un (ou plusieurs capteurs) n'a pas répondu à certains pas la donnée pour ce pas de temps manquant sera noté NA (not Available). Ceci permettra de calculer des taux de valeurs manquantes sur une durée, mieux estimer les probabilités d'apparition, ... Plusieurs exemples d'alignement avec des pas de temps différents sont détaillés : \((1 mois, 1 semaine, 1 journée, 1 heure, 30 minutes, 20 minutes, 10 minutes)\). A choisir en fonction de vos données d'origine et de l'interprétation à mener.

Alignement 1 mois

#etape a1 
date=format(df$temps,"%F")
mois=as.numeric(format(df$temps,"%m"))
df$temps=strptime(format(df$temps, "%Y-%m-15"),format="%Y-%m-%d")
#etape a2
min.date=min(df$temps,na.rm=T)
max.date=max(df$temps,na.rm=T)
a=seq(min.date,max.date,by="1 month")
#etape a3
df2=data.frame(temps=as.POSIXct(a))
df1=merge(df,df2, all=TRUE)
#etape a4
classe=sapply(df1, FUN=class)
numPara=which(classe == "numeric") # possible de selectionner manuellement ex numPara=3:6
df1.M=aggregate(df1[,numPara],by=list(temps=as.character(df1$temps)),
                FUN=function(x){ out=NA; if(sum(is.na(x))<length(x))
                {out=max(x,na.rm=T);}; out})
df1.M$temps=strptime(df1.M$temps,format="%Y-%m-%d")
dfa=df1.M
#Suppressions des données inutiles pour la suite.
rm(date); rm(mois); rm(min.date); rm(max.date); rm(a); rm(df2); rm(df1); rm(numPara); rm(df1.M)
Explications de chaque étape

(a1) Extraction de la date (grâce aux "%F" qui correspond AAAA-MM-JJ) dans un vecteur nommé date. Et extraction du mois de chaque acquisition dans un autre vecteur nommé mois.
Nous considérons le moment de l'acquisition égale au 15 ème jour de chaque mois, il est ensuite mis sous format POSIXt.

(a2) La création de la séquence "a", qui va de la date la plus ancienne à la plus récente. De plus, la fréquence est insérer par l'argument "by".

(a3) Création du tableau, en y incluant seulement le vecteur "a".
Puis fusion du tableau avec le tableau de donnée brute initial (df1).

(a4) Sélection des colonnes contenant que l'on souhaite agrégée. Attention ces colonnes doivent être de type numérique. Voici comment voir la classe des paramètres. De ce nouveau tableau seulement les colonnes voulues sont extraites, et on ne garde que la valeur maximum des doublons créés.

Alignement 1 semaine

Extraction de l'année pour toutes les acquisitions.
Le numéro du jour est repéré. C'est à dire donne le jour en Julien (exemple: le 1 er février correspond au 32ème jour de l'année).
Les données acquisent tous les 7 jours sont saisies, en commencant toujours par le 1er jours de l'année.

annees=format(df$temps,"%Y")
numJour=as.numeric(strftime(df$temps, "%j"))
numJourSemaine=seq(1,364,by=7)
numJourT=sapply(numJour,function(x){index=max(which(x>=numJourSemaine));return(numJourSemaine[index])})
df$temps=strptime(paste(numJourT,annees,sep=" "), "%j %Y")
a=as.character(sort(unique(as.numeric(annees))))
date=rep(a,each=52)
jour=rep(seq(1,364,by=7), length(a))
d=paste(date,jour,sep="-")

df2=data.frame(temps=strptime(d,format="%Y-%j"))
df1=merge(df,df2, by=intersect(names(df),names(df2)),all=TRUE)
classe=sapply(df1, FUN=class)
numPara=which(classe == "numeric")
df1.W=aggregate(df1[,numPara],by=list(temps=as.character(df1$temps)),
               FUN=function(x){ out=NA; if(sum(is.na(x))<length(x))
               {out=max(x,na.rm=T);}; out})
df1.W$temps=strptime(df1.W$temps,format="%Y-%m-%d")
dfa=df1.W
rm(df1); rm(df2); rm(numPara); rm(df1.W); rm(d); rm(jour); rm(a); rm(date)
Détail : Les valeurs enregistrées entre le 1er et le 7ème jour seront considérées comme acquises le 1er jour. Les valeurs enregistrées entre le 8ème et le 15ème jour seront considérées comme acquises le 8 ème jour, etc. Une contrainte est rajoutée pour les derniers jours, car il est fixé qu'il ne peut pas avoir plus de 52 semaines par an. Les valeurs enregistrées au delà de la 51ème semaine (358 jours) seront alors assignées à la dernière semaine. C'est-à-dire les jours allant de 358 à 366.

Alignement 1 journée

Seule la date est également utile elle est mise en format POSIXt en supprimant les heures, minutes et les secondes si présente.

date=format(df$temps,"%F")
jours=as.numeric(format(df$temps,"%d"))
df$temps=strptime(format(df$temps, "%F"),format="%Y-%m-%d")

min.date=min(df$temps,na.rm=T)
max.date=max(df$temps,na.rm=T)
a=seq(min.date,max.date,by="1 day")
d=format(a,"%F")

df2=data.frame(temps=strptime(d,format="%Y-%m-%d"))
df1=merge(df,df2, all=TRUE)
classe=sapply(df1, FUN=class)
numPara=which(classe == "numeric") 
df.J=aggregate(df1[,numPara],by=list(temps=as.character(df1$temps)),
                FUN=function(x){ out=NA; if(sum(is.na(x))<length(x))
                {out=max(x,na.rm=T);}; out})
df.J$temps=strptime(df.J$temps,format="%Y-%m-%d")
dfa=df.J
rm(date); rm(jours); rm(min.date); rm(max.date); rm(a); rm(df2); rm(df1); rm(d); rm(df.J)

Alignement 1 heure

La date et l'heure sont formatées telles que les minutes et les secondes soient considérées nulles HH:00:00. De plus, le format POSIXt est de nouveau imposé.

date=format(df$temps,"%F")
heures=as.numeric(format(df$temps,"%H"))
df$temps=strptime(format(df$temps, "%F %H:00:00"),format="%Y-%m-%d %H:%M:%S")

min.date=min(df$temps,na.rm=T)
max.date=max(df$temps,na.rm=T)
a=seq(min.date,max.date,by="1 hour")

df2=data.frame(temps=strptime(a,format="%Y-%m-%d %H:%M:%S"))
df1=merge(df,df2, all=TRUE)
classe=sapply(df1, FUN=class)
numPara=which(classe == "numeric") # colonnes séléctionnées : 5 à 26

df.H=aggregate(df1[,numPara],by=list(temps=as.character(df1$temps)),
             FUN=function(x){ out=NA; if(sum(is.na(x))<length(x))
            {out=max(x,na.rm=T);}; out})
df.H$temps=strptime(df.H$temps,format="%Y-%m-%d %H:%M:%S")
dfa=df.H
rm(date); rm(heures); rm(min.date); rm(max.date); rm(a); rm(df2); rm(df1); rm(numPara); rm(df10)

Alignement 30 minutes

On considère que [hh:00, hh:29[= hh:15 et [hh:30, hh:59[= hh:45.

date=format(df$temps,"%F %H")
minutes=as.numeric(format(df$temps,"%M"))
minute=rep("45",length(minutes));
minute[minutes<30]="15"
d=paste(date,minute,"00",sep=":")
df$temps=strptime(d,format="%Y-%m-%d %H:%M:%S")

min.date=min(df$temps,na.rm=T)
max.date=max(df$temps,na.rm=T)
a=seq(min.date,max.date,by="1 hour")
date=rep(format(a,"%F %H"),each=2)
minutes=rep(c("15","45"), length(a))
d=paste(date,minutes,"00",sep=":")

df2=data.frame(temps=strptime(d,format="%Y-%m-%d %H:%M:%S"))
df1=merge(df,df2, all=TRUE)
classe=sapply(df1, FUN=class)
numPara=which(classe == "numeric") # colonnes séléctionnées : 5 à 26

df30=aggregate(df1[,numPara],by=list(temps=as.character(df1$temps)),
             FUN=function(x){ out=NA; if(sum(is.na(x))<length(x))
            {out=max(x,na.rm=T);}; out})
df30$temps=strptime(df30$temps,format="%Y-%m-%d %H:%M:%S")
dfa=df30
rm(date); rm(minutes); rm(minute); rm(min.date); rm(max.date); rm(a); rm(d); rm(df2); rm(df1); rm(numPara); rm(df30)

Alignement 20 minutes

On considère que [hh:00, hh:20[= hh:10, [hh:20, hh:40[= hh:30 et pour [hh:40, hh:59]= hh:50.

date=format(df$temps,"%F %H")
minutes=as.numeric(format(df$temps,"%M"))
minute=rep("10",length(minutes))
minute[minutes>19]="30"
minute[minutes>40]="50"
d=paste(date,minute,"00",sep=":")
df$temps=strptime(d,format="%Y-%m-%d %H:%M:%S")

min.date=min(df$temps,na.rm=T)
max.date=max(df$temps,na.rm=T)
a=seq(min.date,max.date,by="1 hour")

date=rep(format(a,"%F %H"),each=3)
minutes=rep(c("10","30","50"), length(a))
d=paste(date,minutes,"00",sep=":")

df2=data.frame(temps=strptime(d,format="%Y-%m-%d %H:%M:%S"))
df1=merge(df,df2, all=TRUE)
classe=sapply(df1, FUN=class)
numPara=which(classe == "numeric") # colonnes séléctionnées : 5 à 26

df20=aggregate(df1[,numPara],by=list(temps=as.character(df1$temps)),
             FUN=function(x){ out=NA; if(sum(is.na(x))<length(x))
            {out=max(x,na.rm=T);}; out})

df20$temps=strptime(df20$temps,format="%Y-%m-%d %H:%M:%S")
dfa=df20
rm(date); rm(minutes); rm(minute); rm(min.date); rm(max.date); rm(a); rm(d); rm(df2); rm(df1); rm(numPara); rm(df20)

Alignement 10 minutes

On considère que [hh:00, hh:10[= hh:05, [hh:10, hh:20[= hh:15, [hh:20, hh:30[= hh:25, [hh:30, hh:40[= hh:35, [hh:40, hh:50]= hh:45 et pour [hh:50, hh:59]= hh:55.

date=format(df$temps,"%F %H")
minutes=as.numeric(format(df$temps,"%M"))
minute=rep("05",length(minutes))
minute[minutes>10]="15"
minute[minutes>20]="25"
minute[minutes>30]="35"
minute[minutes>40]="45"
minute[minutes>50]="55"

d=paste(date,minute,"00",sep=":")
df$temps=strptime(d,format="%Y-%m-%d %H:%M:%S")

min.date=min(df$temps,na.rm=T)
max.date=max(df$temps,na.rm=T)
a=seq(min.date,max.date,by="1 hour")

date=rep(format(a,"%F %H"),each=6)
minutes=rep(c("05", "15","25", "35", "45", "55"), length(a))
d=paste(date,minutes,"00",sep=":")

df2=data.frame(temps=strptime(d,format="%Y-%m-%d %H:%M:%S"))
df1=merge(df,df2, all=TRUE)
classe=sapply(df1, FUN=class)
numPara=which(classe == "numeric") # colonnes séléctionnées : 5 à 26
dfa=aggregate(df1[,numPara],by=list(temps=as.character(df1$temps)),
             FUN=function(x){ out=NA; if(sum(is.na(x))<length(x))
            {out=max(x,na.rm=T);}; out})
dfa$temps=strptime(dfa$temps,format="%Y-%m-%d %H:%M:%S")

Création du fichier compatible avec uHMM

L'interface uHMM exige certaine condition supplémentaire de l'alignement. Il faut avoir une colonne contenant que la date et une autre colonne contenant les heures. Pour cela, la création de 2 vecteurs est essentielle, l'un contenant la date et l'autre contenant l'heure.
"dfa" étant votre tableau de données alignées que vous souhaitez faire lire par l'interface. "%F" retire les années, le mois et le jour (AAAA-MM-JJ) et "%X" retire les heures, les minutes et les secondes (hh:mm:ss). Reste alors à créer ensuite le fichier compatible avec l'interface au format compatible.

colonneDate=as.character(format(dfa$temps,"%F"))
colonneHeure=as.character(format(dfa$temps,"%X"))
iTemps=grep(pattern="temps",names(dfa))
df.uHMM=data.frame(Dates=colonneDate,Hours=colonneHeure,(dfa[,-iTemps]))
write.table(df.uHMM,file="uHMMformattedData.txt",dec='.',sep="\t", quote=FALSE, row.names=FALSE)