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 :

Fusionner un champ en ligne et en colonne


Sujet :

R

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2018
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2018
    Messages : 27
    Par défaut Fusionner un champ en ligne et en colonne
    Bonjour à tous,

    Je cherche à faire une opération qui semble simple au premier abord mais sur laquelle je peine depuis quelques jours.

    Je cherche en effet à fusionner (joindre) un tableau sur une matrice, avec fusion en ligne et en colonne d'un champ.
    Il s'agit d'une matrice dont les noms de lignes et de colonnes sont identiques (origine / destination). Il y a donc le même nb de lignes que de colonnes.

    Les lignes et les colonnes de cette matrice sont les identifiants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
         001   002   003
    001   x     x     x
    002   x     x     x
    003   x     x     x
    Je voudrais créer une colonne et une ligne supplémentaires à partir d'un tableau du type suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    001 oui
    002 oui
    003 non
    afin d'obtenir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
         001   002   003   c4
    001   x     x     x    oui
    002   x     x     x    oui
    003   x     x     x    non
    l4    oui  oui  non
    Mais je n'y parviens pas.
    Je suis habitué à utiliser merge (ce qui pourrait résoudre le pb pour les lignes) mais je ne parviens pas à le faire pour les lignes et les colonnes.

    Est-ce que certains d'entre vous sauraient faire ça ?

    Merci par avance,
    G.

  2. #2
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Août 2007
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2007
    Messages : 125
    Par défaut
    Bonjour,
    Voici une première proposition.

    La matrice:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    M <- matrix(sample(LETTERS,9),ncol=3,
                dimnames = list(c("001","002","003"),c("001","002","003")))
     
        001 002 003
    001 "V" "M" "I"
    002 "J" "D" "S"
    003 "L" "C" "O"
    Le tableau (ici c'est un vecteur colonne):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    V <- matrix(c("oui", "non", "oui"), 
                dimnames = list(c("001","003","002"),NULL))
     
        [,1] 
    001 "oui"
    003 "non"
    002 "oui"
    Il est noter qu'ici je suppose que l'ordre des lignes dans M et V peut être différent.

    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
     
    fct <- function(M, V){
        ## Build an empty matrix with NaN values
        ## The number of rows and column is increased by one
        res <- matrix(NaN, ncol=ncol(M)+1, nrow=nrow(M)+1,
                      dimnames = list(c(rownames(M),paste0("r",nrow(M)+1)),
                                      c(colnames(M),paste0("c",ncol(M)+1))))
     
        ## Copy the matrix M in the first columns and rows of the new matrix res
        res[1:nrow(M), 1:ncol(M)] <- M
     
        ## We assume that the order of names can be different between V and M
        newPos <- sapply(rownames(V), function(v) which (v==rownames(M)))
     
        ## add the values in the last row and last col
        res[1:nrow(M),nrow(M)+1] <- V[newPos,1]
        res[nrow(M)+1, 1:nrow(M)] <- V[newPos,1]
     
        return(res)
    }
    Si j'applique cette fonction, voici le résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    newM <- fct(M, V)
     
        001   002   003   c4   
    001 "V"   "M"   "I"   "oui"
    002 "J"   "D"   "S"   "oui"
    003 "L"   "C"   "O"   "non"
    r4  "oui" "oui" "non" "NaN"
    J'espère avoir pu vous aider.

    Bon week-end
    Olivier

  3. #3
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2018
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2018
    Messages : 27
    Par défaut
    Merci beaucoup pour cette réponse.

    Il m'est difficile de savoir si cette méthode convient, car je maîtrise pas la lecture de la fonction.

    J'ai testé sur ma matrice (1055 colonnes x 1055 lignes) et de mon tableau à fusionner (1055 observations et 2 variables) mais cela ne semble pas fonctionner, mais il m'est difficile de développer davantage mon explication...

    Ce qui en ressort est cette erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Error in xj[i] : invalid subscript type 'list'
    Si jamais quelqu'un qui maîtrise la fonction a une idée...?

  4. #4
    Membre Expert
    Inscrit en
    Novembre 2009
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 707
    Par défaut Fusionner un champ en ligne et en colonne
    Bonjour,

    Une autre approche :

    • Si toutes les lignes sont communes et dans le même ordre, il est possible d'utiliser les fonctions bind_cols() et bind_rows() du package dplyr :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    > M <- matrix(c("A","B","C", "D","E","F", "G","H","I"),ncol=3,
    +             dimnames = list(c("001","002","003"),c("001","002","003")))
    > M.df <- as.data.frame(M)
    > M.df
        001 002 003
    001   A   D   G
    002   B   E   H
    003   C   F   I
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    V <- matrix(c("oui", "oui", "non"), 
                dimnames = list(c("001","002","003"),names="V4"))
    > V.df <- as.data.frame(V)
    > V.df
         V4
    001 oui
    002 oui
    003 non
    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
    > library(dplyr)
    > T.df <- bind_cols(M.df,V.df)
    > T.df <- bind_rows(T.df,as.data.frame(t(V.df)))
    Warning messages:
    1: In bind_rows_(x, .id) : Unequal factor levels: coercing to character
    2: In bind_rows_(x, .id) :
      binding character and factor vector, coercing into character vector
    ...
    > row.names(T.df) <- names(T.df)
    > T.df
        001 002 003   V4
    001   A   D   G  oui
    002   B   E   H  oui
    003   C   F   I  non
    V4  oui oui non <NA>

    • S'il manque des lignes ou qu'elles ne sont pas dans le même ordre, il est possible d'utiliser la fonction merge() et la fonction bind_rows() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    > M <- matrix(c("A","B","C", "D","E","F", "G","H","I"),ncol=3,
    +             dimnames = list(c("001","002","003"),c("001","002","003")))
    > M.df <- as.data.frame(M)
    > M.df$id <- row.names(M.df)
    > M.df
        001 002 003  id
    001   A   D   G 001
    002   B   E   H 002
    003   C   F   I 003
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    > V <- matrix(c("non","oui"), 
    +             dimnames = list(c("003","001"),"V4"))
    > V.df <- as.data.frame(V)
    > V.df$id <- row.names(V.df)
    > V.df
         V4  id
    003 non 003
    001 oui 001
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    > T.df <- merge(M.df,V.df,by="id",all=TRUE)[,-1]
    > library(dplyr)
    > T.df <- bind_rows(T.df,as.data.frame(t(V.df)))[-length(T.df),]
    Warning messages:
    1: In bind_rows_(x, .id) : Unequal factor levels: coercing to character
    2: In bind_rows_(x, .id) :
      binding character and factor vector, coercing into character vector
    > row.names(T.df) <- names(T.df)
    > T.df
        001  002 003   V4
    001   A    D   G  oui
    002   B    E   H <NA>
    003   C    F   I  non
    V4  oui <NA> non <NA>
    Cordialement,

  5. #5
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2018
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2018
    Messages : 27
    Par défaut
    Merci mgdondon pour cette réponse complète, il semblerait que ta seconde solution soit adaptée à mon exemple. Merci beaucoup.
    Je dois utiliser ton deuxième exemple car je ne suis pas convaincu à 100% que les ordres soient respectés dans ma matrice.



    • De plus, j'ai un petit soucis avec mes noms de colonnes. Mes tableaux sont importés via read.csv2 et si les noms de lignes sont respectés (001 par ex.), les colonnes quant à elles sont "rebaptisées" (X001 par ex.) ce qui semble poser problème.

      J'ai donc tenté de convertir les noms afin qu'ils soient identiques. Mais si je convertis les noms des lignes (en X001 par ex.) et des colonnes (en X001 par ex), cela ne semble pas fonctionner :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      Error in bind_rows_(x, .id) : 
        Column `X001` can't be converted from integer to factor


    J'ai l'impression que je ne suis pas loin du résultat attendu... mais qu'il manque un petit détail.

Discussions similaires

  1. [WD-2016] Parcourir une tableau avec des lignes et des colonnes fusionnées
    Par Anaxode dans le forum VBA Word
    Réponses: 3
    Dernier message: 04/10/2017, 16h11
  2. Réponses: 0
    Dernier message: 29/03/2017, 15h37
  3. [XL-2016] fusionner les deux lignes avec le même nom dans une colonne
    Par methos01 dans le forum Excel
    Réponses: 4
    Dernier message: 27/03/2017, 15h26
  4. Réponses: 1
    Dernier message: 23/12/2013, 16h58
  5. identifier la dernière ligne d'une colonne avec VB Excel
    Par schwoby dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 12/08/2007, 18h14

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