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
.