[Résolu] Subset d'intervalle variable

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

Laëtitia VIBERT
Messages : 42
Enregistré le : 16 Avr 2019, 10:13

[Résolu] Subset d'intervalle variable

Messagepar Laëtitia VIBERT » 03 Juin 2019, 13:52

Bonjour,

j'aimerais extraire des sous-df dans certains cas, pour n'obtenir que des df de 4 lignes max ; les df de base allant de 1 à 8 lignes.
Par exemple, pour un df de 7 lignes, cela me ferait un sub de 4 et un sub de 3, ou l'inverse, peu importe. Pour 5, 3 et 2 etc...

J'ai essayé le code suivant, mais il est très lourd et peu efficace, car je suis obligée de passer à la main le nombre de lignes que je souhaite :

Code : Tout sélectionner

l1 <- data.frame("id"=c(1,1,1,2,2,3,3,3,3,3), "trip" = c(1,2,3,1,2,1,2,3,4,5))
l2 <- data.frame("id"=c(1,1,1,2,2,3,3,3,3,3), "trip" = c(1,2,3,1,2,1,2,3,4,5),"file" = c("fileA","fileB","fileC","fileD","fileE","fileF","fileG","fileH","fileI","fileJ"))

for (i in 1:nrow(l1)) {
    id <- l1$id[i]
    trip <- l1$trip[i]
   
    trip.tab <- l2[which(l2$id ==id & l2$trip == trip),]
    if (nrow(trip.tab) > 4) {
      j <- 1
      n <- 1
      trip.tab_2 <- trip.tab
      while (j <= (nrow(trip.tab))+4) {
        trip.tab <- trip.tab_2[c(j:(j+2)),]  #erreur si le nbr de lignes n'est pas un multiple de 3
        #suite du script...
        j <- j+3
        n <- n+1
      }
    } else {
      #suite du script
    }
  }


J'ai aussi essayé 3 if imbriqués :

Code : Tout sélectionner

if (nrow(trip.tab) <= 4) {
} else {
   if (nrow(trip.tab) == 5 | nrow(trip.tab) == 6) {
   trip.tab1 <- trip.tab[1:3,]
        trip.tab2 <- trip.tab[4:nrow(trip.tab),]
   } else {
      if (nrow(trip.tab) == 7 | nrow(trip.tab) == 8) {
      trip.tab1 <- trip.tab[1:3,]
             trip.tab2 <- trip.tab[4:6,]
             trip.tab3 <- trip.tab[7:nrow(trip.tab),]
      }
   }
}

Mais c'est très très lourd (mais ça tourne ^^)

Je me demandais si il y avait une option dans la fonction subset permettant d'intégrer un pas variable, mais je ne trouve pas.

En vous remerciant pour votre aide précieuse,
L.
L.

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

Re: Subset d'intervalle variable

Messagepar Mickael Canouil » 03 Juin 2019, 14:49

Bonjour,

les conditions ne pas vraiment évidentes...
"trip.tab" dans votre exemple ne fera absolument jamais plus d'une ligne...

Peut-être pouvez-vous indiquer la forme que devrait avoir votre objet final ?

J'y vais d'une pure supposition/interprétation de ce que vous voulez :

Code : Tout sélectionner

l2 <- data.frame(
  "id" = c(1, 1, 1, 2, 2, 3, 3, 3, 3, 3),
  "trip" = c(1, 2, 3, 1, 2, 1, 2, 3, 4, 5),
  "file" = c("fileA", "fileB", "fileC", "fileD", "fileE", "fileF", "fileG", "fileH", "fileI", "fileJ")
)

split(x = l2, f = l2$id)
#> $`1`
#>   id trip  file
#> 1  1    1 fileA
#> 2  1    2 fileB
#> 3  1    3 fileC
#>
#> $`2`
#>   id trip  file
#> 4  2    1 fileD
#> 5  2    2 fileE
#>
#> $`3`
#>    id trip  file
#> 6   3    1 fileF
#> 7   3    2 fileG
#> 8   3    3 fileH
#> 9   3    4 fileI
#> 10  3    5 fileJ


Au passage, pourquoi avoir l1 et l2, sachant que l2 contient intégralement l1 ?

Cordialement,
Mickaël
mickael.canouil.fr | rlille.fr

Laëtitia VIBERT
Messages : 42
Enregistré le : 16 Avr 2019, 10:13

Re: Subset d'intervalle variable

Messagepar Laëtitia VIBERT » 03 Juin 2019, 15:06

Bonjour,
merci pour la réponse, en effet, à vouloir trop simplifier, j'en perds des données.
En réalité, pour 1 id et 1 trip, l2 peut avoir 1 à 8 lignes (selon la durée en jours en fait), chaque jour correspondant à une référence de "files", d'où des trip.tab de taille variable (1 à 8 lignes).
En fait, l1 correspond à un énorme df que je ne veux pas modifier, j'ai donc créé l2, qui ne contient que les colonnes qui m'intéressent, auxquelles j'ai ajouté la colonne "files".

A la fin, je souhaite un df avec id - trip - files (chaque file correspondant à 1 jour de trip, et le df ne devant pas excéder 3 ou 4 lignes).

Code : Tout sélectionner

id   trip   files
1   1   fileA
1   1   B
1   1   C
1   2   D
1   2   E
2   1   ...
2   1   ...
2   1   ...   
2   1   ...
2   1   ...

me donnerait :

Code : Tout sélectionner

id   trip   files
1   1   A
1   1   B
1   1   C

id   trip   files
1   2   D
1   2   E

id   trip   files
2   1   ...
2   1   ...
2   1   ...

id   trip   files
2   1   ...
2   1   ...
L.

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

Re: Subset d'intervalle variable

Messagepar Mickael Canouil » 03 Juin 2019, 15:17

Pour résumer, vous voulez des trios (maximum) par id ?
Mickaël
mickael.canouil.fr | rlille.fr

Laëtitia VIBERT
Messages : 42
Enregistré le : 16 Avr 2019, 10:13

Re: Subset d'intervalle variable

Messagepar Laëtitia VIBERT » 03 Juin 2019, 15:19

Je souhaite avoir 3 ou 4 lignes par trip, afin de ne pas me retrouver avec des df à 1 ligne (par ex, si j'ai un df initial de 4 lignes ou de 7 -> je garde les 4 et je fais 3 et 4).
L.

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

Re: Subset d'intervalle variable

Messagepar Mickael Canouil » 03 Juin 2019, 15:38

Un jeu de donnée plus "réaliste"

Code : Tout sélectionner

library(tidyverse)
l2 <- tibble::tibble("id" = rep(c(1, 2, 3, 4, 5, 6), c(3, 2, 4, 5, 1, 8))) %>%
  group_by(id) %>%
  mutate(
    trip = seq(n())
  ) %>%
  ungroup() %>%
  mutate(file = paste0("file", LETTERS[1:n()]))


Le code et le résultat:
split() permet de découper un data.frame selon un facteur, ici en premier lieu sur "id".
Puis sur le résultat de cut(), qui permet de créer des intervalles, ici en fonction de la division par 3.

Code : Tout sélectionner

res <- lapply(
  X = split(x = l2, f = l2$id),
  FUN = function(idf) {
    block_size <- c(3, 4)[which.min(nrow(idf) %% c(3, 4))]
   
    if (nrow(idf)>block_size) {
      split(x = idf, f = cut(x = 1:nrow(idf), ceiling(nrow(idf) / block_size)))
    } else {
      list(idf)
    }
  }
)
unlist(res, recursive = FALSE, use.names = FALSE)
#> [[1]]
#> # A tibble: 3 x 3
#>      id  trip file
#>   <dbl> <int> <chr>
#> 1     1     1 fileA
#> 2     1     2 fileB
#> 3     1     3 fileC
#>
#> [[2]]
#> # A tibble: 2 x 3
#>      id  trip file
#>   <dbl> <int> <chr>
#> 1     2     1 fileD
#> 2     2     2 fileE
#>
#> [[3]]
#> # A tibble: 4 x 3
#>      id  trip file
#>   <dbl> <int> <chr>
#> 1     3     1 fileF
#> 2     3     2 fileG
#> 3     3     3 fileH
#> 4     3     4 fileI
#>
#> [[4]]
#> # A tibble: 3 x 3
#>      id  trip file
#>   <dbl> <int> <chr>
#> 1     4     1 fileJ
#> 2     4     2 fileK
#> 3     4     3 fileL
#>
#> [[5]]
#> # A tibble: 2 x 3
#>      id  trip file
#>   <dbl> <int> <chr>
#> 1     4     4 fileM
#> 2     4     5 fileN
#>
#> [[6]]
#> # A tibble: 1 x 3
#>      id  trip file
#>   <dbl> <int> <chr>
#> 1     5     1 fileO
#>
#> [[7]]
#> # A tibble: 4 x 3
#>      id  trip file
#>   <dbl> <int> <chr>
#> 1     6     1 fileP
#> 2     6     2 fileQ
#> 3     6     3 fileR
#> 4     6     4 fileS
#>
#> [[8]]
#> # A tibble: 4 x 3
#>      id  trip file
#>   <dbl> <int> <chr>
#> 1     6     5 fileT
#> 2     6     6 fileU
#> 3     6     7 fileV
#> 4     6     8 fileW


edit: ajout du modulo pour définir la taille d'un "block", c'est-à-dire 3 ou 4 lignes.
Mickaël
mickael.canouil.fr | rlille.fr

Laëtitia VIBERT
Messages : 42
Enregistré le : 16 Avr 2019, 10:13

Re: Subset d'intervalle variable

Messagepar Laëtitia VIBERT » 03 Juin 2019, 16:14

Wow ! ça a l'air de marcher, j'essaie de comprendre et d'adapter à mes jeux de données, merci !
EDIT: ça marche. Je passe donc de 66 lignes à 11 lignes, sacrément efficace !
Mille merci !
L.


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité