Synchronisation de deux tableaux de donnée

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Nicolas Rochat
Messages : 18
Enregistré le : 22 Nov 2013, 12:18

Synchronisation de deux tableaux de donnée

Messagepar Nicolas Rochat » 30 Oct 2014, 11:34

Bonjour ,

je cherche à synchroniser deux tableaux de donnée ne comprenant pas les mêmes timecode et je ne trouve pas de fonction ou de méthode pour réaliser l'opération de manière automatique.

Exemple premier tableau

Code : Tout sélectionner

event<-c("A","B","C","D","E")
time<-seq(0,40,by=10)
data1<-data.frame(event,time)



exemple deuxième tableau

Code : Tout sélectionner

time2<-seq(0,49,1)
valeur<-rnorm(50,0,1)
data2<-data.frame(time,valeur)


le résultat voulu

Code : Tout sélectionner

event2<-c(rep("A",10),rep("B",10),rep("C",10),rep("D",10),rep("E",10))
data3<-data.frame(event2,time2,valeur)


Contrairement à l'exemple les données ne seront pas équivalentes en temps donc je cherche une solution pour que les éléments soient tous à leur place.

merci

Florent Aubry
Messages : 324
Enregistré le : 25 Juin 2010, 10:21

Messagepar Florent Aubry » 30 Oct 2014, 14:42

Qu'entendez-vous par "synchroniser" deux tableaux, ne serait-ce pas plutôt les fusionner en utilisant une ou des variables 'pivot' permettant de faire correspondre une ligne du premier tableau à une ligne du second (ou plus complexe). Cette opération appelée aussi jointure de tables dans les bases de données se réalise sous R par la fonction merge (package base) ou par join dans le package dplyr.

Nicolas Rochat
Messages : 18
Enregistré le : 22 Nov 2013, 12:18

Messagepar Nicolas Rochat » 30 Oct 2014, 14:58

je pensais synchronisation car ce sont des temps de réponse.

La fonction join semble marcher mais elle me retourne de N.A.

Code : Tout sélectionner

join(data2,data1,by="time")


Il y a un moyen de pour avoir les event à la place des N.A.

merci

Florent Aubry
Messages : 324
Enregistré le : 25 Juin 2010, 10:21

Messagepar Florent Aubry » 30 Oct 2014, 15:18

Personnellement, j'utilise merge qui est largement suffisant pour une grande majorité des cas. Essayer donc avec cette fonction.

Précision Que ce soit join ou merge, la jointure retourne par défaut NA s'il n'y a aucune correspondance entre les 'pivots' (clés en langage de bases de données) dans les deux tables (i.e., aucune des clés d'une table ne se retrouve dans l'autre). Le comportement devant ce cas est contrôlé par un argument (all, all.x et all.y pour merge). Donc si l'appel de merge par défaut retourne NA, je coderai alors :

Code : Tout sélectionner

merge( data2, data1, by="time", all=TRUE)


N.B. : En relisant, je m'aperçoit que la variable pivot est codé time dans le premier tableau et time2 dans le second. Il faut donc spécifier correctement la jointure qui devrait être dans votre cas :

Code : Tout sélectionner

merge( data2, data1, by.x="time2", by.y="time", all=TRUE)

Eric Casellas
Messages : 767
Enregistré le : 06 Jan 2009, 14:59

Messagepar Eric Casellas » 30 Oct 2014, 15:31

Bonjour,

Je ne suis pas bien sûr d'avoir compris précisément ce que tu veux faire et comment tu veux combiner tes tableaux, et aussi il me semble que dans tes codes tu a du te tromper pour data2 qui utilise time au lieu de time2...

Sinon un bout de code basé sur ton exemple pour construire data3 à partir de data1 et data2 sans passer par event2, time2 ou valeur :

Code : Tout sélectionner

event <- c("A","B","C","D","E")
time <- seq(0,40,by=10)
(data1 <- data.frame(event,time))

time2 <- seq(0,49,1)
valeur <- rnorm(50,0,1)
(data2 <- data.frame(time2,valeur))

event2 <- c(rep("A",10),rep("B",10),rep("C",10),rep("D",10),rep("E",10))
(data3 <- data.frame(event2,time2,valeur))


event3 <- as.vector(sapply(data1$event, function(x) rep(x, nrow(data2)/nrow(data1)), simplify=TRUE));
(data4=data.frame(event2=event3,
                  time2=data2$time,
                  valeur=data2$valeur))

identical(data3, data4)
Eric

Eric Wajnberg
Messages : 776
Enregistré le : 11 Aoû 2008, 15:37
Contact :

Messagepar Eric Wajnberg » 30 Oct 2014, 15:59

un point supplémentaire. "time" est déjà le nom d'un objet (fonction) existant sous R et il n'est pas très judicieux, je pense, d'utiliser comme nom d'un objet à créer le nom d'un objet existant déjà. C'est une source de confusion, voire d'erreur.

HTH, Eric.

Nicolas Rochat
Messages : 18
Enregistré le : 22 Nov 2013, 12:18

Messagepar Nicolas Rochat » 30 Oct 2014, 17:23

non ce n'est pas la source d'une erreur mais bon je remplace


Code : Tout sélectionner

event<-c("A","B","C","D","E")
temps<-seq(0,40,by=10)
data1<-data.frame(event,temps)




temps<-seq(0,49,1)
valeur<-rnorm(50,0,1)
data2<-data.frame(temps,valeur)



join(data2,data1,by="temps")






Code : Tout sélectionner

 temps      valeur event
1      0  1.11747291     A
2      1 -0.30251659  <NA>
3      2 -0.46453644  <NA>
4      3 -0.67909982  <NA>
5      4 -1.79868673  <NA>
6      5  1.15941849  <NA>
7      6 -0.40861226  <NA>
8      7  1.80768569  <NA>
9      8 -1.71717158  <NA>
10     9  0.52100718  <NA>
11    10 -0.64207704     B
12    11 -0.21499801  <NA>
13    12  1.49325520  <NA>
14    13  0.81173816  <NA>
15    14  1.81777535  <NA>
16    15  1.32659897  <NA>
17    16 -0.81946676  <NA>
18    17 -1.15855309  <NA>
19    18  0.21190691  <NA>
20    19 -2.67962533  <NA>
21    20 -0.16484118     C
22    21  0.65570116  <NA>
23    22 -1.38037193  <NA>
24    23 -0.06968503  <NA>
25    24  1.30178499  <NA>
26    25  0.01221727  <NA>
27    26  0.12881131  <NA>
28    27 -1.66116704  <NA>
29    28  0.49722093  <NA>
30    29 -0.36429873  <NA>
31    30 -0.08406805     D
32    31  0.27018908  <NA>
33    32 -0.66517067  <NA>
34    33  0.51538730  <NA>
35    34 -0.41473488  <NA>
36    35 -1.35234398  <NA>
37    36 -0.89784582  <NA>
38    37 -0.11428381  <NA>
39    38 -1.12358537  <NA>
40    39  0.46812330  <NA>
41    40  1.39021601     E
42    41  0.48207570  <NA>
43    42  1.09775024  <NA>
44    43 -0.85187700  <NA>
45    44 -0.01830001  <NA>
46    45 -0.79266136  <NA>
47    46  1.54972528  <NA>
48    47  0.99111559  <NA>
49    48 -0.35143293  <NA>
50    49  0.03098632  <NA>



La fonction join marche presque comme il faut en fait le problème est que à la place des NA on voudrait afficher l'event qui est concerné ( en dessous de A des A, en dessous de B des B .....)

Florent Aubry
Messages : 324
Enregistré le : 25 Juin 2010, 10:21

Messagepar Florent Aubry » 31 Oct 2014, 08:10

Dans ton cas, le plus simple est de créer dans les deux tableaux une pseudo-variable 'pivot' qui vaudra

Code : Tout sélectionner

floor( donnees$time / 10)
et de faire la jointure sur cette pseudo-variable. Ensuite, si tu veux l'éliminer, tu peux utiliser le code suivant :

Code : Tout sélectionner

subset( merge( ..., by="nom.pseudo.variable"), select=-nom.pseudo.variable)


ATTENTION : Dans merge le nom du pivot est passé sous forme de chaine de caractères mais dans subset, on passe le nom de l'objet dans l'environnement des données. Il ne faut donc pas mettre le nom entre doubles quotes.

Eric Casellas
Messages : 767
Enregistré le : 06 Jan 2009, 14:59

Messagepar Eric Casellas » 31 Oct 2014, 09:28

La fonction join marche presque comme il faut en fait le problème est que à la place des NA on voudrait afficher l'event qui est concerné ( en dessous de A des A, en dessous de B des B .....)


C'est normal, join fait ce qu'elle est censée faire...
tu n'as de correspondance entre les temps de tes 2 tableaux que 1 valeur sur 10 (0, 10, 20, ...) donc pour les autres il te met du NA...
Eric

Nicolas Rochat
Messages : 18
Enregistré le : 22 Nov 2013, 12:18

Messagepar Nicolas Rochat » 11 Jan 2015, 11:53

Je me suis penché sur le problème de manière plus approfondi et j'ai crée une fonction qui semble répondre à ma demande.

Code : Tout sélectionner

jointime<-function(dataa=NULL,datab=NULL,nomtemps,nrbcol){
  ########le nom de la fonction temps doit être similaire dans les deux tableaux
 
 
  ###organisation des données temporelle
  names(dataa)[ names(dataa) == nomtemps ] <- "time"
  dataa<-dataa[order(dataa$time),]
 
  names(datab)[ names(datab) == nomtemps ] <- "time"
  datab<-datab[order(datab$time),]
 
  ######création d'un ligne temporel recouvrant l'ensemble des données
  time<-seq(from=ifelse(min(dataa$time)<=min(datab$time),min(dataa$time),min(datab$time)),
            to=ifelse(max(dataa$time)>=max(datab$time),max(dataa$time),max(datab$time)), by=1)
 
  temps<-data.frame(time)
 
  library(dplyr)
  library(plyr)
 
 
  ######joinction des deux tableaux
  datafull<-join(temps,dataa, by="time")
  datacom<-join(datafull,datab,by="time")
 
 
  ######extraction des lignes contenant des NA en dehors de la colonne temps (lignes inutiles)
  datacom<-datacom[rowSums(is.na(datacom))!=(ncol(datacom)-1), ]
 
  #####complément des NA sur les lignes restantes
  library(DataCombine)
  for(i in 1:nrbcol){
    datacom<-FillDown(datacom,colnames(datacom[i]))
  }
  datacom
}



exemple d'utilisation


Code : Tout sélectionner

event<-c("A","B","C","D","E")
temps<-seq(0,40,by=10)
data1<-data.frame(event,temps)




temps<-seq(0,49,1)
valeur<-rnorm(50,0,1)
data2<-data.frame(temps,valeur)



a<-jointime(dataa=data1,datab=data2,nomtemps="temps",nrbcol=3)
head(a)

  time event     valeur
1    0     A  1.1406556
2    1     A -0.7514697
3    2     A -0.4012853
4    3     A  0.4267697
5    4     A  0.4324722
6    5     A -0.5729482







Merci à tous de vos éclairages qui m'ont guidé

PS: le code doit pouvoir largement être améliorable

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Messagepar François Bonnot » 12 Jan 2015, 08:39

Ou encore :

Code : Tout sélectionner

data3 <- merge(data1,data2,all=TRUE)
data3$event <- data3$event[!is.na(data3$event)][cumsum(ifelse(is.na(data3$event),0,1))]
François


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité

cron