IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

R Discussion :

Comparer des lignes entre elles


Sujet :

R

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Avril 2019
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte de base de données

    Informations forums :
    Inscription : Avril 2019
    Messages : 26
    Par défaut Comparer des lignes entre elles
    Bonjour,

    J'ai un grand jeu de donnée provenant d'arbres.
    Dans la première colonne, il y a ce que l'on appelle des numéro de clones. Chaque numéro de clone est présent en plusieurs copie (de 1 à 5). Il s'agit d'arbres qui sont normalement identiques
    Dans les colonnes suivante, il y a des allèles (80 allèles en tout).

    Le but est de vérifier si les arbres portant le même numéro de clone ont bien tout leurs allèles identiques.
    Si au moins deux allèles diffèrent, alors les arbres sont considérés comme différents, ce ne sont pas de vrais clones. Il y pas mal de données manquantes pour certains allèles, qui ne doivent pas être considérées comme des différences.

    Clones Individu Allele1 Allele2 Allele3 etc
    clone1 1 A T CG etc
    clone1 2 A T CG etc
    clone1 3 A T CG etc
    clone1 4 A T AT etc
    clone1 5 A T CG etc
    clone2 etc
    clone2 etc

    -> l'individu 5 parmi les 5 "clone1" est différent. Ce n'est pas un clone.

    Voici comment j'envisageais la chose, en terme de logique. Peut-être avez vous mieux a proposer?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    # sélection de tout les arbres issu d'un clone.
    # -> return nombre de données manquantes pour chaque arbre.
    # 
    # création d'un vecteur contenant les allèles supposés corrects
    # -> On regarde tout les clones, et on estime que si un allèle apparait au moins trois fois pour cette colonne, alors il est correct. Autrement, il est faux.
    # 
    # comparaison de chaque échantillons avec le vecteur supposé correct
    # -> return nombre de différences (ne pas comparer si allèle manquant)
    #   si nb de difference>2 = individus différents
    #   si nb de difference<2 = individus identiques.
     
    #output :
    #un data frame contenant tout les arbres considéré comme différent du vecteur supposé correct. Return nombre de differences.
    #
    Quelles fonctions dois-je utiliser pour mener a bien cette tache selon vous?

    Merci de votre aide.

  2. #2
    Membre émérite
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corse (Corse)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 491
    Par défaut
    bonjour, j'ai fait un petit script à tester
    la fonction principale est verifier_clone


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    ## df fichier des clones :  les données manquantes sur les allèles ==> NA
     
    df<-df %>% select_all(str_to_lower) ## on mets en minuscule nom des colonnes
    #  "clones"   "individu" "allele1"  "allele2"  "allele3"  ...
     
    # ajout colonne serie qui aggrege  les allèles
    df <-df %>% bind_cols(  unite(data=df %>% select(-1,-2),col = "serie",names(df)[c(-1,-2)],sep="_")) %>% 
      mutate(serie = str_replace_all(serie,"_NA_","_*_")) ## om mets une étoile * si donnée sur allèle est manquante
     
    remplacer_manquant <- function(list_pattern_clone,list_pattern_diff)  {
      ## fonction qui remplace les données manquantes par la valeur de la donnée des clones
      res <- map(1:nrow(list_pattern_diff),
                 ~map_chr(1:ncol(list_pattern_diff),~ifelse(list_pattern_diff[.y,.x]=="*",list_pattern_clone[.x],list_pattern_diff[.y,.x]),.y=.x))  
      matrix(unlist(res),ncol = ncol(list_pattern_diff),byrow = T)
    }
     
     
    verifier_clone <- function(clone){
      ## le résultat de la fonction est un dataframe des individus différents pour au moins 2 allèles
      ## clones serie     nb individus difference
     
      ## on filtre  par le clone
      dff <- df %>% filter(clones == clone)
     
      ##on regroupe par clone les séries
      df2 <- dff %>%  group_by(clones,serie) %>% summarise(nb= n(), individus = str_c(individu,collapse = ",")) 
     
      if(max(df2$nb)<3){
        message("problème pas de clones")
      }else if(max(df2$nb == 5)){
        message(str_c(clone," ok"))
      } else{
        ## on récupère la série du clone  et la ou les 2 séries des individus différents
        pattern_clone=df2  %>% filter(nb == max(nb)) %>% pull(serie)
        pattern_diff =df2  %>% filter(nb != max(nb)) %>% ungroup()%>% select(serie)
     
     
      ## on découpe les séries en allèle
        # série ou pattern clone
      list_pattern_clone=str_split(pattern_clone,"_",simplify = T)
        # pattern individu différents
      list_pattern_diff=map(1:nrow(pattern_diff),~str_split(pattern_diff %>% slice(.x) %>% pull(serie),"_",simplify= T))
      list_pattern_diff=matrix(unlist(list_pattern_diff),nrow=length(list_pattern_diff),byrow = T)
     
      ## on remplace les manquants (*) par la valeur de l'allèle correspondant au pattern (= série) du clone
      ## pour ne pas les comptabliser comme différence
      list_pattern_diff =remplacer_manquant(list_pattern_clone,list_pattern_diff)
     
      ## on génère résultat  des individus différents si différence porte sur au moins 2 allèles 
     res <- map_df(1:nrow(list_pattern_diff),~df2 %>% filter(serie == str_c(list_pattern_diff[.x,],collapse ="_")) %>% 
                 mutate(difference = sum(is.na(str_match(list_pattern_clone,list_pattern_diff[.x,]))))) %>% filter(difference>1)
     
      }
    }
     
    ## pour trouver tous les individus différents
    resultat <- map_df(unique(df$clones),verifier_clone)

  3. #3
    Membre averti
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Avril 2019
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte de base de données

    Informations forums :
    Inscription : Avril 2019
    Messages : 26
    Par défaut
    Bonjour

    Un grand merci pour votre aide.

    Cependant, il a des parties de votre code où je ne comprends pas

    Notamment à la ligne au début ou vous écrivez
    select(-1,-2),col = "serie",names(df)[c(-1,-2)]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    df <-df %>% bind_cols(unite(data=df %>% select(-1,-2),col = "serie",names(df)[c(-1,-2)],sep="_")) %>% 
      mutate(serie = str_replace_all(serie,"_NA_","_*_")) ## on mets une étoile * si donnée sur allèle est manquante
    A quoi sert cette ligne ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     individus = str_c(individu,collapse = ",")) # fusionne plusieurs vecteur en une chaine de caractère séparée par des virgules
    Merci pour votre aide.

    Code complet que j'ai quasiment pas modifié.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    mydata<-read.table(file='Bilan_201905.csv', header = TRUE,sep=';')
     
    unique_clone_id <- unique(mydata$clone_id)
     
    ## Les données manquantes doivent être remplacées par "NA" dans le fichier source.
     
    ## Ajout d'une colonne serie qui aggrege les allèles(=ensemble des x alleles pour un individu) 
    df <-df %>% bind_cols(unite(data=df %>% select(-1,-2),col = "serie",names(df)[c(-1,-2)],sep="_")) %>% 
      mutate(serie = str_replace_all(serie,"_NA_","_*_")) ## om mets une étoile * si donnée sur allèle est manquante
     
    ##########################################################
    ### fonction qui remplace les allèles manquants par l'allèle le plus présent chez les autres clone d'un même ramet.
    ##########################################################
    remplacer_manquant <- function(list_pattern_clone,list_pattern_diff)  {
     
      res <- map(1:nrow(list_pattern_diff),
                 ~map_chr(1:ncol(list_pattern_diff),~ifelse(list_pattern_diff[.y,.x]=="*",list_pattern_clone[.x],list_pattern_diff[.y,.x]),.y=.x))  
      matrix(unlist(res),ncol = ncol(list_pattern_diff),byrow = T)
    }
     
    ##########################################################
    ### fonction qui vérifie si les clones d'un ramet sont identiques ###
    ##########################################################
     
    verifier_clone <- function(unique_clone){
     
      ## on filtre  par le clone
      filter_clones <- df %>% filter(mydata$clone_id == unique_clone)
     
      ## on regroupe par série les individus avec un numéro de clone identique.
      group_clones <- dff %>%  group_by(unique_clone,série) %>% summarise(nb= n()) 
     
        if(max(df2$nb)<3){ # si le nombre de ligne identiques est inferieur à 3
        message("erreur, le nombre de clones identiques n'est pas suffisant (<3)")
        return(unique_clone_id)
     
        }else if(max(df2$nb==5)){ # si les nombre de ligne identiques est égal à 5
        message(str_c(clone," ok, les 5 clones sont identiques"))
     
        }else{
        pattern_clone= df2  %>% filter(nb == max(nb)) %>% pull(serie) #on récupère les clones identiques
        pattern_diff = df2  %>% filter(nb != max(nb)) %>% ungroup()%>% select(serie) #on isole les clones différents
     
      ## on découpe les séries d'allèle
     
           # série d'alleles pour les bon clones (redondance>3)
        list_pattern_clone=str_split(pattern_clone,"_",simplify = T) 
     
           # série d'alleles clones différents
        list_pattern_diff=map(1:nrow(pattern_diff),~str_split(pattern_diff %>% slice(.x) %>% pull(serie),"_",simplify= T))
        list_pattern_diff=matrix(unlist(list_pattern_diff),nrow=length(list_pattern_diff),byrow = T)
     
        ## on remplace les valeurs manquantess (*) par la valeur de l'allèle correspondant au 
        ## pattern de la série des bons clone pour ne pas les comptabliser comme différence
        list_pattern_diff =remplacer_manquant(list_pattern_clone,list_pattern_diff)
     
        ## On ajoute l'individu à un data.frame si la différence porte sur au moins 2 allèles 
        res <- map_df(1:nrow(list_pattern_diff),~df2 %>% filter(serie == str_c(list_pattern_diff[.x,],collapse ="_")) %>% 
                        mutate(difference = sum(is.na(str_match(list_pattern_clone,list_pattern_diff[.x,]))))) %>% filter(difference>1)
     
      }
    }
     
    ## pour trouver tous les individus différents
    resultat <- map_df(unique(df$clones),verifier_clone)

  4. #4
    Membre émérite
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corse (Corse)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 491
    Par défaut
    bonjour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select(-1,-2),col = "serie",names(df)[c(-1,-2)]
    on peut enlever qui ne sert à rien!



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    individus = str_c(individu,collapse = ",")
    dans la ligne de code je regroupe par clones et serie (génotype serait peut-être mieux) après je fait une aggrégation
    je compte le nombre d'individu qui ont la même serie pour un clone donné et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    individus = str_c(individu,collapse = ",")
    me donne sous forme de string la liste de ces individus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    num_ind<-c(1,2,3)
    list_num_ind<-str_c(num_ind, collapse = "_") ## donne "1_2_3"

  5. #5
    Membre averti
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Avril 2019
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte de base de données

    Informations forums :
    Inscription : Avril 2019
    Messages : 26
    Par défaut
    Bonjour,

    En réalité, c'est pas que je ne comprend pas les fonction utilisées, c'est plutot que je ne vois pas toujours vers où vous allez, et pourquoi vous faite ceci ou cela.

    Par exemple, je ne comprend pas pourquoi faite
    select(-1,-2]
    . Il n'y a pas de telles valeurs dans le data.frame.
    Je ne comprend pas non plus a quoi sert
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    individus = str_c(individu,collapse = ",")
    puisque vous ne le réutilisez pas dans la suite du code, sauf erreur de ma part.

  6. #6
    Membre émérite
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corse (Corse)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 491
    Par défaut
    ok, on s'était mal compris

    un particularité de la fonction select : elle permet de sélectionner les colonnes soit par leur nom soit par leur indice donc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    df%>%select(clones, individus)  ## selection uniquemement des colonnes clones et individu du dataframe df
    # est équivalent à
    df%>%select(1,2) ## on suppose comme dans ton exemple que ce sont les 2 premières colonnes de df
    # quand on met des nombres négatifs on sélectionne toutes les colonnes sauf la une et la deux
    ]df%>%select(-1,-2) ##ou
    df%>% select(-clones, -individus) # on sélectionne toutes les colonnes (tous les alleles dans ton cas) sauf les colonnes clones et individu
    ##après avec la fonction unite je crée une colonne serie qui est l'aggrégation de tous les allèles sous forme de string, les alleles étant séparé par un underscore


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    resultat <- map_df(unique(df$clones),verifier_clone)
    le dataframe resultat a 4 colonnes
    clones ## nom du clone étudié
    serie ## serie de l'individu différent
    individus ## le numero de l'individu different obtenu par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    individus = str_c(individu,collapse = ",")
    difference ## nombre de différence avec la serie "clone"

    si tu teste avec le petit exemple que tu as donné tu obtiens un dataframe resultat vide car le seul individu différent n'a qu'une différence (tu veux au moin 2) , si tu mets en commentaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    %>% filter(difference>1
    dans la dernière ligne de code de la fonction verifier_clone()
    tu obtiens le dataframe suivant

    clones serie ; nb ;individus; difference

    clone1; A_T_AT; 1 ;4 ; 1

    j'espère que c'est plus clair

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [BI4] Recherche formule pour comparer les lignes entre elles
    Par GTime dans le forum Webi
    Réponses: 1
    Dernier message: 24/10/2018, 14h14
  2. Comparer la présence des lignes entre deux feuilles
    Par Miigui dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 21/09/2017, 14h01
  3. [Lazarus] MD5 : comment comparer des valeurs entre elles ?
    Par MedGIR dans le forum Lazarus
    Réponses: 1
    Dernier message: 26/08/2009, 21h30
  4. Réponses: 3
    Dernier message: 14/06/2009, 00h14
  5. comparer des dates entre elles
    Par cyrano_de_bergerac dans le forum Collection et Stream
    Réponses: 14
    Dernier message: 07/06/2007, 15h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo