web-dev-qa-db-fra.com

Renommer plusieurs colonnes par noms

Quelqu'un aurait déjà dû poser cette question, mais je n'ai pas trouvé de réponse. Dis que j'ai:

x = data.frame(q=1,w=2,e=3, ...and many many columns...)  

quel est le moyen le plus élégant de renommer un sous-ensemble arbitraire de colonnes, dont je ne connais pas nécessairement la position, en d'autres noms arbitraires?

par exemple. Dites que je veux renommer "q" et "e" en "A" et "B", quel est le code le plus élégant pour le faire?

Évidemment, je peux faire une boucle:

oldnames = c("q","e")
newnames = c("A","B")
for(i in 1:2) names(x)[names(x) == oldnames[i]] = newnames[i]

Mais je me demande s'il existe un meilleur moyen? Peut-être en utilisant certains des paquets? (plyr::rename etc.)

51
qoheleth

setnames du data.tablepackage fonctionnera sur data.frames ou data.tables

library(data.table)
d <- data.frame(a=1:2,b=2:3,d=4:5)
setnames(d, old = c('a','d'), new = c('anew','dnew'))
d


 #   anew b dnew
 # 1    1 2    4
 # 2    2 3    5

Notez que les modifications sont effectuées par référence, donc pas de copie (même pour les data.frames!)

79
mnel

Avec dplyr vous feriez:

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)

df %>% rename(A = q, B = e)

#  A w B
#1 1 2 3

Ou si vous voulez utiliser des vecteurs, comme suggéré par @ Jelena-bioinf:

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)

oldnames = c("q","e")
newnames = c("A","B")

df %>% rename_at(vars(oldnames), ~ newnames)

#  A w B
#1 1 2 3
44
Gorka

Une autre solution pour les cadres de données qui ne sont pas trop volumineux est (en s’appuyant sur la réponse @thelatemail):

x <- data.frame(q=1,w=2,e=3)

> x
  q w e
1 1 2 3

colnames(x) <- c("A","w","B")

> x
  A w B
1 1 2 3

Alternativement, vous pouvez également utiliser:

names(x) <- c("C","w","D")

> x
  C w D
1 1 2 3

De plus, vous pouvez également renommer un sous-ensemble des noms de colonnes:

names(x)[2:3] <- c("E","F")

> x
  C E F
1 1 2 3
28
Jaap

J'ai donc récemment rencontré ce problème moi-même, si vous n'êtes pas sûr que les colonnes existent et que vous voulez seulement renommer celles qui le font: 

existing <- match(oldNames,names(x))
names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]
10
JoelKuiper

Voici le moyen le plus efficace que j'ai trouvé pour renommer plusieurs colonnes à l'aide d'une combinaison d'opérations purrr::set_names() et de quelques opérations stringr.

library(tidyverse)

# Make a tibble with bad names
data <- tibble(
    `Bad NameS 1` = letters[1:10],
    `bAd NameS 2` = rnorm(10)
)

data 
# A tibble: 10 x 2
   `Bad NameS 1` `bAd NameS 2`
   <chr>                 <dbl>
 1 a                    -0.840
 2 b                    -1.56 
 3 c                    -0.625
 4 d                     0.506
 5 e                    -1.52 
 6 f                    -0.212
 7 g                    -1.50 
 8 h                    -1.53 
 9 i                     0.420
 10 j                     0.957

# Use purrr::set_names() with annonymous function of stringr operations
data %>%
    set_names(~ str_to_lower(.) %>%
                  str_replace_all(" ", "_") %>%
                  str_replace_all("bad", "good"))

# A tibble: 10 x 2
   good_names_1 good_names_2
   <chr>               <dbl>
 1 a                  -0.840
 2 b                  -1.56 
 3 c                  -0.625
 4 d                   0.506
 5 e                  -1.52 
 6 f                  -0.212
 7 g                  -1.50 
 8 h                  -1.53 
 9 i                   0.420
10 j                   0.957
6
Matt Dancho

S'appuyant sur la réponse de @ user3114046:

x <- data.frame(q=1,w=2,e=3)
x
#  q w e
#1 1 2 3

names(x)[match(oldnames,names(x))] <- newnames

x
#  A w B
#1 1 2 3

Cela ne dépend pas d'un ordre spécifique des colonnes dans le jeu de données x.

5
thelatemail

Cela changerait toutes les occurrences de ces lettres dans tous les noms:

 names(x) <- gsub("q", "A", gsub("e", "B", names(x) ) )
4
42-
names(x)[names(x) %in% c("q","e")]<-c("A","B")
3
James King

Vous pouvez obtenir le jeu de noms, l'enregistrer en tant que liste, puis renommer en bloc la chaîne. Un bon exemple de cela est lorsque vous effectuez une transition longue à large sur un jeu de données:

names(labWide)
      Lab1    Lab10    Lab11    Lab12    Lab13    Lab14    Lab15    Lab16
1 35.75366 22.79493 30.32075 34.25637 30.66477 32.04059 24.46663 22.53063

nameVec <- names(labWide)
nameVec <- gsub("Lab","LabLat",nameVec)

names(labWide) <- nameVec
"LabLat1"  "LabLat10" "LabLat11" "LabLat12" "LabLat13" "LabLat14""LabLat15"    "LabLat16" " 
2
Boyce Byerly

Si la table contient deux colonnes portant le même nom, le code est le suivant:

rename(df,newname=oldname.x,newname=oldname.y)
1
varun

Il y a beaucoup de réponses, alors je viens d'écrire la fonction pour pouvoir copier/coller. 

rename <- function(x, old_names, new_names) {
    stopifnot(length(old_names) == length(new_names))
    # pull out the names that are actually in x
    old_nms <- old_names[old_names %in% names(x)]
    new_nms <- new_names[old_names %in% names(x)]

    # call out the column names that don't exist
    not_nms <- setdiff(old_names, old_nms)
    if(length(not_nms) > 0) {
        msg <- paste(paste(not_nms, collapse = ", "), 
            "are not columns in the dataframe, so won't be renamed.")
        warning(msg)
    }

    # rename
    names(x)[names(x) %in% old_nms] <- new_nms
    x
}

 x = data.frame(q = 1, w = 2, e = 3)
 rename(x, c("q", "e"), c("Q", "E"))

   Q w E
 1 1 2 3
1
Dan

Sidenote, si vous voulez concaténer une chaîne à tous les noms de colonnes, vous pouvez simplement utiliser ce code simple.

colnames(df) <- paste("renamed_",colnames(df),sep="")
1
Corey Levinson

Si une ligne de données contient les noms pour lesquels vous souhaitez modifier toutes les colonnes, vous pouvez le faire.

names(data) <- data[row,]

data étant donné est votre cadre de données et row est le numéro de ligne contenant les nouvelles valeurs.

Ensuite, vous pouvez supprimer la ligne contenant les noms avec

data <- data[-row,]
0
CaffeineConnoisseur

C’est la fonction dont vous avez besoin:

rename <-function(x){
  oldNames = c("a","b","c")
  newNames = c("d","e","f")
  existing <- match(oldNames,names(x))
  names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]
  return(x)
}
0
Zuti