Alguien debería haberle preguntado ya, pero yo no podía encontrar una respuesta. Decir que tengo:

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

¿cuál es la forma más elegante para cambiar el nombre de un subconjunto arbitrario de las columnas, cuya posición no necesariamente sé, en algunos otros nombres arbitrarios?

por ejemplo, supongamos que queremos cambiar el nombre de "q" y "e" en "A" y "B", ¿cuál es la más elegante de código para hacer esto?

Obviamente, puedo hacer un bucle:

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

Pero me pregunto si hay una manera mejor? Tal vez el uso de algunos de los paquetes? (plyr::rename etc.)

InformationsquelleAutor qoheleth | 2014-01-08

14 Comentarios

  1. 80

    setnames de la data.tablepaquete de trabajo en data.frames o 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

    Tenga en cuenta que los cambios se hacen por referencia, por lo que no copia (incluso para los datos.marcos!)

    • Para las llegadas tarde aquí – También echar un vistazo a Joel respuesta por debajo de la cual cubre la comprobación de las columnas existentes en caso de que usted tiene una lista de cambios de nombre que no todos pueden estar presentes por ejemplo, old = c("a", "d", "e")
    • Me pregunto, ¿este trabajo, si sólo desea cambiar el nombre de un subconjunto / algunas de las columnas en lugar de todos ellos? Así que si yo tenía un marco de datos de diez columnas y desea cambiar el nombre de _id_firstname a nombre y _id_lastname a apellido, pero dejar el resto de los ocho columnas intactas, puedo hacerlo o tengo que lista todas las columnas?
    • proporcione el subconjunto de nuevos y viejos nombres, y va a trabajar.
  2. 49

    Con dplyr que haría:

    library(dplyr)
    
    df = data.frame(q = 1, w = 2, e = 3)
    
    df %>% rename(A = q, B = e)
    
    #  A w B
    #1 1 2 3

    O si desea utilizar vectores, como sugerido por @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
    • el usuario le preguntó acerca de pasar old y new nombres como los vectores, creo
    • Gracias @Jelena-bioinf. He modificado la respuesta de incluir su sugerencia.
  3. 29

    Otra solución para dataframes que no son demasiado grandes es (edificio en @thelatemail respuesta):

    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

    Alternativamente, también puede utilizar:

    names(x) <- c("C","w","D")
    
    > x
      C w D
    1 1 2 3

    Además, usted puede también cambiar el nombre de un subconjunto de la columnnames:

    names(x)[2:3] <- c("E","F")
    
    > x
      C E F
    1 1 2 3
  4. 11

    Así que hace poco me encontré a mí mismo, si usted no está seguro de si las columnas de existir y sólo desea cambiar el nombre de los que lo hacen:

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

    Aquí es la forma más eficaz que he encontrado para cambiar el nombre de varias columnas utilizando una combinación de purrr::set_names() y un par de stringr operaciones.

    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
    • Esta debe ser la respuesta, pero podría usted probablemente también deberían ampliar lo que el ~ y . argumentos en la set_names() tubo.
  6. 5

    Edificio en @user3114046 la respuesta:

    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

    Esto no va a ser dependientes de un determinado orden de las columnas en la x conjunto de datos.

    • He upvoted tu respuesta, pero todavía me pregunto si existe una forma más elegante de hacer esto, particularmente los métodos que cambiar el nombre por nombre, en lugar de por la posición
    • es el cambio de nombre por nombre! No hay ninguna entrada aquí que es un vector de posición como match se encarga de eso. El mejor que vas a hacer es, probablemente, @mnel del setnames respuesta.
    • todavía es una especie de cambio de nombre por la posición, porque, como usted dijo, aunque yo no tengo que especificar explícitamente un vector de posición, match es todavía una posición orientada al comando. En este espíritu, les considerará @user3114046 la respuesta de la posición de base como bien (a pesar de que la %in% comando toma el cuidado (o intenta) de las cosas). Por supuesto, supongo que se puede argumentar que todos los comandos de la posición orientada cuando nos profundizar en el mecanismo de bajo nivel…. pero eso no es a lo que me refiero… los datos.tabla de respuesta es genial, porque no hay múltiples llamadas de la name comandos.
  7. 4

    Esto iba a cambiar todas las apariciones de las letras de todos los nombres:

     names(x) <- gsub("q", "A", gsub("e", "B", names(x) ) )
    • Yo no creo que esto es especialmente elegante, una vez pasado un par de cambiar el nombre de las instancias.
    • No soy lo suficientemente bueno para lanzar un gsubfn respuesta. Quizás G. Grothendieck va a venir. Él es el regex-meister.
  8. 4
    names(x)[names(x) %in% c("q","e")]<-c("A","B")
    • No del todo, porque como ya he dicho, no saben necesariamente la posición de las columnas, su solución sólo funciona si oldnames se ordenan para que oldnames[i] se produce antes de oldnames[j] para i<j.
  9. 2

    Usted puede obtener el nombre del set, guárdelo como una lista y, a continuación, hacer su masiva de cambiar el nombre de la cadena. Un buen ejemplo de esto es cuando usted está haciendo un tiempo de transición en un conjunto de datos:

    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" " 
    • Esta es una buena respuesta, muy general.
  10. 1

    Mucho de la de ordenación de las respuestas, así que acabo de escribir la función, así que usted puede copiar/pegar.

    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
    • rename(x, c("q", "e"), c("Q", "E")) parece que ha dejado de trabajar en dplyr cambiar el nombre?
  11. 1

    Nota al margen, si usted desea concatenar una cadena con todos los nombres de columna, usted puede utilizar este sencillo código.

    colnames(df) <- paste("renamed_",colnames(df),sep="")
  12. 1

    Si la tabla contiene dos columnas con el mismo nombre, a continuación, el código va como este,

    rename(df,newname=oldname.x,newname=oldname.y)
  13. 0

    Si una fila de datos contiene los nombres que desea cambiar todas las columnas que usted puede hacer

    names(data) <- data[row,]

    Dado data es su dataframe y row es el número de fila que contiene los nuevos valores.

    A continuación, puede quitar la fila que contiene los nombres con

    data <- data[-row,]
  14. 0

    Esta es la función que usted necesita:
    A continuación, sólo tiene que pasar el x en un cambio de nombre(X) y que se cambie el nombre de todos los valores que aparecen y si no en no no error

    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)
    }

Dejar respuesta

Please enter your comment!
Please enter your name here