occurrence successive

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

Laure Trudel
Messages : 24
Enregistré le : 26 Mar 2013, 11:02

occurrence successive

Messagepar Laure Trudel » 13 Avr 2019, 05:35

Bonjour,

J'ai une colonne avec des valeurs 1 ou 2 qui peuvent être successive ou alterner c'est-à-dire 1,1,1,2,1,2,1,2,2,2. Je cherche à identifier les lignes ou j'ai la valeur 2 qui se succède au minimum 3 fois et pour lesquelles je veux associer un nom de segment dans une autre colonne. Si la valeur 1 se succèdent 2 fois ou plus après cette succession de 2 alors la prochaine succession de 2 sera associer à un nouveau nom de segments et ainsi de suite. J'ai fait une boucle avec des if pour le moment mais je me demandais s'il y avait une meilleure écriture ou une fonction que je pourrais utiliser.
De plus, le point qui me pose un problème c'est lorsque j'ai des lignes avec 2,2,2,1,2,1,2,2,2 par exemple ou alors je peux considérer qu'un seul segment. Je n'ai pas trouvé la solution pour associer qu'un seul même segment aux différentes valeurs comme cet expl

valeur nom_segment
2 segment_1
2 segment_1
2 segment_1
1 segment_1
2 segment_2
2 segment_2
1 segment_2
2 segment_3
1 segment_3
2 segment_4
2 segment_4
1 NA
1 NA
1 NA
1 NA

merci,

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

Re: occurrence successive

Messagepar François Bonnot » 15 Avr 2019, 06:33

Bonjour,
C'est un peu compliqué... il faudrait un (petit) jeu de données où tous les cas cités apparaissent et le résultat que vous voudriez obtenir.
François

Mickael Canouil
Messages : 599
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: occurrence successive

Messagepar Mickael Canouil » 15 Avr 2019, 08:14

Bonjour,

l'exemple me laisse perplexe...
"j'ai la valeur 2 qui se succède au minimum 3 fois"
uniquement le "premier segment" est dans ce cas, pourtant vous nommez tous vos segments.

Voici une piste de solution (j'ai mis le minimum pour un segment à 2)

Code : Tout sélectionner

.data <- data.frame(
  values = c(2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L),
  segment_names = NA
)

values_rle <- rle(.data$values)

pos_segment <- which(values_rle$values==2 & values_rle$lengths>=2)
values_rle$values <- rep("NA", length(values_rle$values))
for (ipos in seq(pos_segment)) {
  values_rle$values[pos_segment[ipos]] <- paste0("segment_", ipos)
}


.data$segment_names <- inverse.rle(values_rle)

.data
#>    values segment_names
#> 1       2     segment_1
#> 2       2     segment_1
#> 3       2     segment_1
#> 4       1            NA
#> 5       2     segment_2
#> 6       2     segment_2
#> 7       1            NA
#> 8       2            NA
#> 9       1            NA
#> 10      2     segment_3
#> 11      2     segment_3
#> 12      1            NA
#> 13      1            NA
#> 14      1            NA


Cordialement,
Mickaël

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

Re: occurrence successive

Messagepar Eric Casellas » 15 Avr 2019, 09:44

Bonjour,

Il y a la fonction de base rle qui permet de trouver les valeurs consécutives répétées

Code : Tout sélectionner

?rle
x <- rev(rep(6:10, 1:5))
rle(x)


Eric
Eric

Laure Trudel
Messages : 24
Enregistré le : 26 Mar 2013, 11:02

Re: occurrence successive

Messagepar Laure Trudel » 15 Avr 2019, 17:29

Bonjour,

Merci pour vos réponses.J'avais vu que l'on pouvait utiliser la fonction rle qui est utile pour les cas simples mais c'est pour les cas particuliers que je cherche une solution éventuelle.
Les segments commencent quand au moins 3 valeurs successives ou plus égales à 2 et ils s'arrêtent lorsque l'on a au moins 2 valeurs successives égales à 1.
Pour être plus claire voici un exemple de suite de valeurs que je rencontre avec différents cas de figure et le résultat que je voudrais obtenir:


Valeur segment_name
2 segment_1
2 segment_1
2 segment_1
1 segment_1
2 segment_1
1 segment_1
2 segment_1
2 segment_1
1 segment_1
2 segment_1
2 segment_1
2 segment_1
1 NA
1 NA
1 NA
2 segment_2
2 segment_2
2 segment_2
2 segment_2
1 segment_2
2 segment_2
1 segment_2
2 segment_2
2 segment_2
2 segment_2
1 NA
1 NA
2 NA
2 NA
1 NA
1 NA
2 NA
1 NA


Merci

Mickael Canouil
Messages : 599
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: occurrence successive

Messagepar Mickael Canouil » 16 Avr 2019, 09:04

avec une modification de la piste que j'avais donné, c'est-à-dire en exploitant la fonction "rle":

Code : Tout sélectionner

.data <- utils::read.table(text = "Valeur segment_name
2 segment_1
2 segment_1
2 segment_1
1 segment_1
2 segment_1
1 segment_1
2 segment_1
2 segment_1
1 segment_1
2 segment_1
2 segment_1
2 segment_1
1 NA
1 NA
1 NA
2 segment_2
2 segment_2
2 segment_2
2 segment_2
1 segment_2
2 segment_2
1 segment_2
2 segment_2
2 segment_2
2 segment_2
1 NA
1 NA
2 NA
2 NA
1 NA
1 NA
2 NA
1 NA", header = TRUE)

Code : Tout sélectionner

values_rle <- rle(.data$Valeur)

# Get start position three times "2"
pos_segment_start <- which(values_rle$values==2 & values_rle$lengths>=3)
# Get end position two times "1"
pos_segment_end <- which(values_rle$values==1 & values_rle$lengths>=2)
# Locate where the segment should end in the vector of starting positions
pos_segment_end <- pos_segment_end[!duplicated(findInterval(pos_segment_end, pos_segment_start))]
# Get the smallest starting position for each end position
pos_segment_start <- tapply(
  X = pos_segment_start,
  INDEX = findInterval(pos_segment_start, pos_segment_end),
  FUN = min
)

# change the values in the rle object with new names based on start/end position
values_rle$values <- rep("NA", length(values_rle$values))
for (ipos in seq(pos_segment_start)) {
  values_rle$values[pos_segment_start[ipos]:(pos_segment_end[ipos]-1)] <- paste0("segment_", ipos)
}
# revert rle to get segment names
.data$segment_names <- inverse.rle(values_rle)


Code : Tout sélectionner

.data
#>    Valeur segment_name segment_names
#> 1       2    segment_1     segment_1
#> 2       2    segment_1     segment_1
#> 3       2    segment_1     segment_1
#> 4       1    segment_1     segment_1
#> 5       2    segment_1     segment_1
#> 6       1    segment_1     segment_1
#> 7       2    segment_1     segment_1
#> 8       2    segment_1     segment_1
#> 9       1    segment_1     segment_1
#> 10      2    segment_1     segment_1
#> 11      2    segment_1     segment_1
#> 12      2    segment_1     segment_1
#> 13      1         <NA>            NA
#> 14      1         <NA>            NA
#> 15      1         <NA>            NA
#> 16      2    segment_2     segment_2
#> 17      2    segment_2     segment_2
#> 18      2    segment_2     segment_2
#> 19      2    segment_2     segment_2
#> 20      1    segment_2     segment_2
#> 21      2    segment_2     segment_2
#> 22      1    segment_2     segment_2
#> 23      2    segment_2     segment_2
#> 24      2    segment_2     segment_2
#> 25      2    segment_2     segment_2
#> 26      1         <NA>            NA
#> 27      1         <NA>            NA
#> 28      2         <NA>            NA
#> 29      2         <NA>            NA
#> 30      1         <NA>            NA
#> 31      1         <NA>            NA
#> 32      2         <NA>            NA
#> 33      1         <NA>            NA


Ce n'est peut-être pas le plus efficace/jolie, mais le résultat est là.

Cordialement,
Mickaël

Laure Trudel
Messages : 24
Enregistré le : 26 Mar 2013, 11:02

Re: occurrence successive

Messagepar Laure Trudel » 16 Avr 2019, 17:51

Merci Mickaël mais malheureusement ça ne fonctionne pas. J'ai des segments associés à des valeurs successives de 1 et d'autres incohérences.
Par exemple le même segment pour une succession de 2 et de 1 ou une succession de deux valeurs de 1 qui sont associés au segment précédent alors qu'il ne devrait pas etc... Mon jeu de donnée est assez gros donc je ne peux pas tout présenter ici. Cela est t il possible de vous envoyer un jeu de données plus gros?

merci,

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

Re: occurrence successive

Messagepar François Bonnot » 17 Avr 2019, 06:20

Cela est t il possible de vous envoyer un jeu de données plus gros?

Bonjour,
il faudrait envoyer un sous-ensemble du jeu de données avec les situations qui posent problème.
Quelques dizaines de lignes devraient suffire.
Utiliser dput() pour insérer les données:
http://forums.cirad.fr/logiciel-R/viewtopic.php?f=1&t=3302
François

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

Re: occurrence successive

Messagepar François Bonnot » 17 Avr 2019, 08:14

Re-bonjour,
Je propose la fonction suivante.
Elle est un peu lourde et doit pouvoir être simplifiée par quelqu'un qui maîtriserait bien les expressions régulières.
A vérifier si elle fonctionne dans tous les cas...

Code : Tout sélectionner

get.segment <- function(v) {
    v0 <- paste0(v,collapse='')
    start <- gregexpr("2{3,}",v0)[[1]]
    stop <- gregexpr("1{2,}",v0)[[1]]
    i <- rep(0,length(v))
    i[start] <- 2
    i[stop] <- 1
    i0 <- paste0(i,collapse='')
    g <- gregexpr("2(.*?)1",i0)[[1]]
    m <- matrix(c(g,attr(g,"match.length")+g-2),nrow=2)
    segment <- rep(NA,length(v))
    for (j in 1:nrow(m)) segment[m[j,1]:m[j,2]] <- j
    segment
}

A appliquer au .data du message précédent de Mickaël:

Code : Tout sélectionner

cbind(.data,segment=get.segment(.data$Valeur))
François

Logez Maxime
Messages : 2897
Enregistré le : 26 Sep 2006, 11:35

Re: occurrence successive

Messagepar Logez Maxime » 17 Avr 2019, 09:46

Bonjour,

une proposition :

Code : Tout sélectionner

test <- paste(tab$Valeur, collapse="")
library(stringi)
auxi <- stri_locate_all(test, regex= "2{3,}(1{1}[^1]+|[^1]+)+(?=1{2})")[[1]]
res <- rep(NA, nrow(tab))
for (i in 1:nrow(auxi)) res[auxi[i,1]:auxi[i,2]] <- sprintf("segment_%s", i)
all.equal(as.character(tab$segment_name), res)
[1] TRUE
Après ici on ne vérifie pas qu'on a une valeur supérieur à 1 mais une valeur différente de 1 (on peut remplacer [^1] par [2-9] si on reste sur des chiffres mais dès qu'on aura des nombres il faudra complexifier un peu).

Cordialement,
Maxime

Laure Trudel
Messages : 24
Enregistré le : 26 Mar 2013, 11:02

Re: occurrence successive

Messagepar Laure Trudel » 17 Avr 2019, 15:42

Bonjour,

Merci beaucoup pour vos retours.
voici un lien https://we.tl/t-GXgAIGabmz pour télécharger une partie de mon jeu de donnée de 1000 lignes environ.j'ai donc préféré utiliser un autre moyen que la fonction dput(). j'ai essayé votre code sur le jeu de données que je vous ai envoyé dans le lien François mais ça n'a pas marché. Par contre celui de Maxime a presque fonctionné sauf à la fin du jeu de données ou j'ai des NA au lieu d'avoir un nouveau segment pour des valeurs de 2 successives.

Laure Trudel
Messages : 24
Enregistré le : 26 Mar 2013, 11:02

Re: occurrence successive

Messagepar Laure Trudel » 17 Avr 2019, 20:20

J'ai aussi remarqué dans le code de Maxime que quand j'ai 3 valeurs de 2 successives je devrais avoir un segment or si j'ai 111,222,111111 alors j'ai des NA.
J'ai modifié
auxi <- stri_locate_all(test1, regex= "2{3,}(1{1}[^1]+|[^1]+)+(?=1{2})")[[1]]
en mettant un 2{2,} au lieu 2{3,}
mais alors j'ai des segments si j'ai 2 valeurs de 2 successives ce que je ne veux pas...compliqué!

Autre chose peut-on le faire avec une valeur continue, par exemple, comprise entre 1 et 2 où j'ai au minimum 3 valeurs >= 1.65 alors j'associe un segment sinon NA et le segment s'arrête qd j'ai au moins 2 valeurs < 1.65 ?

Mickael Canouil
Messages : 599
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: occurrence successive

Messagepar Mickael Canouil » 18 Avr 2019, 08:21

Laure Trudel a écrit :Autre chose peut-on le faire avec une valeur continue, par exemple, comprise entre 1 et 2 où j'ai au minimum 3 valeurs >= 1.65 alors j'associe un segment sinon NA et le segment s'arrête qd j'ai au moins 2 valeurs < 1.65 ?


Le plus simple, ne serait-il pas d'essayer pour le savoir ?
je vous suggère de creuser un peu la question des expressions régulières, avec par exemple les opérateurs
Mickaël


Retourner vers « Questions en cours »

Qui est en ligne

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