Search code examples
rdataframenames

Rename columns that are not together using colnames()


Considering the simple code,

df <- data.frame(x = 1:2,
                 y = 3:4,
                 z = 5:6)

How can I rename with one line columns x and z using colnames()?

I understand that colnames(df)[1:2] <- c("p", "q") would modify the first two headers, but how can I rename not-together columns?

I am aware of different commands that can do the job, just wondering if there is a colnames() solution.


Solution

  • Instead of 1:2, which is selecting column 1 and column 2, you could use c(1,3) for column 1 and 3. Also I would use names for a data.frame instead of colnames but colnames would also work.

    names(df)[c(1,3)] <- c("p", "q")
    

    In case the positions are not known, but the names, you can use match to get the desired columns.

    names(df)[match(c("x", "z"), names(df))] <- c("p", "q")
    

    Or a more robust version in case a match is not found.

    i <- c(x = "p", z = "q")[names(df)]
    j <- !is.na(i)
    names(df)[j] <- i[j]
    

    Or a variant without using intermediate steps.

    names(df) <- c(x = "p", z = "q", setNames(names(df), names(df)))[names(df)]
    
    names(df) <- (\(.) c(x = "p", z = "q", setNames(., .))[.])(names(df)) #Variant
    

    or using transform.

    names(df) <- transform(as.list(setNames(names(df), names(df))), x="p", z="q")
    

    Have also a look at Rename multiple columns by names and Canonical tidyverse method to update some values of a vector from a look-up table.


    Note: In the source of colnames<- you find the lines:

        if (is.data.frame(x)) {
            names(x) <- value
        }
    

    So I prefer to use names instead of colnames when I have a data.frame.