Reputation: 1251
I have some variables like below:
colnames(samp)
[1] "Q11_1_1" "Q11_1_2" "Q11_1_3" "Q11_1_4" "Q11_1_5" "Q11_1_6" "Q11_1_7" "Q11_1_8" "Q11_1_9" "Q11_1_10"
[11] "Q11_1_11" "Q11_1_12" "Q11_1_99" "Q11_2_1" "Q11_2_2" "Q11_2_3" "Q11_2_4" "Q11_2_5" "Q11_2_6" "Q11_2_7"
[21] "Q11_2_8" "Q11_2_9" "Q11_2_10" "Q11_2_11" "Q11_2_12" "Q11_2_99"
I want to exchange the value in the middle and at the end e.g.
Q11_1_1 -> Q11_1_1
Q11_1_2 -> Q11_2_1
...
Q11_1_99 -> Q11_99_2
I can do it this way (but this is quite time consuming).
samp %>%
rename(Q11_1_2 = Q11_2_1)
Any idea how to do this?
Upvotes: 2
Views: 628
Reputation: 269461
Here are two different alternatives. The first is more compact but the second avoids regular expressions. No packages are used in either.
1) sub Use sub
like this:
# test data
DF <- data.frame("Q11_1_1" = 1, "Q11_1_2" = 2, "Q11_1_3" = 3)
names(DF) <- sub("(\\d+)_(\\d+)$", "\\2_\\1", names(DF))
DF
## Q11_1_1 Q11_2_1 Q11_3_1
## 1 1 2 3
2) read.table This alternative is longer but does not use any regular expressions.
# test data
DF <- data.frame("Q11_1_1" = 1, "Q11_1_2" = 2, "Q11_1_3" = 3)
names(DF) <- with(read.table(text = names(DF), sep = "_"), paste(V1, V3, V2, sep="_"))
DF
## Q11_1_1 Q11_2_1 Q11_3_1
## 1 1 2 3
If not all the columns are of the indicated form this will pick those that are out and just transform them. In this case we want them all so it is not needed but if there were other columns it could be used.
ix <- grep("_.*_", names(DF)) # 1:3
names(DF)[ix] <-
with(read.table(text = names(DF)[ix], sep = "_"), paste(V1, V3, V2, sep="_"))
Upvotes: 4
Reputation: 768
Using stringr
:
library(stringr)
# test data
df <- data.frame("Q11_1_1" = 1, "Q11_1_2" = 32, "Q11_1_3" = 3, "Q11_1_99" =
4)
ColNames = colnames(df)
# initialise an empty vector to hold new column names
new_ColNames = vector()
for (i in 1:length(ColNames)) {
splited = str_split(ColNames[i], "_")
new_ColNames[i] = paste(splited[[1]][1],splited[[1]][3],splited[[1]][2],
sep = "_")
}
# assign new colmun names to the df
colnames(df) = new_ColNames
Output:
> df
Q11_1_1 Q11_2_1 Q11_3_1 Q11_99_1
1 1 32 3 4
Upvotes: 0
Reputation: 72623
You could do a split - order - paste approach.
colnames(samp) <-
mapply(function(x) paste(x[c(1, 3:2)], collapse="_"), strsplit(colnames(samp), "_"))
colnames(samp)
# [1] "Q11_1_1" "Q11_1_2" "Q11_1_3" "Q11_1_4" "Q11_1_5" "Q11_1_6" "Q11_1_7" "Q11_1_8"
# [9] "Q11_1_9" "Q11_1_10" "Q11_1_11" "Q11_1_12" "Q11_1_99" "Q11_2_1" "Q11_2_2" "Q11_2_3"
# [17] "Q11_2_4" "Q11_2_5" "Q11_2_6" "Q11_2_7" "Q11_2_8" "Q11_2_9" "Q11_2_10" "Q11_2_11"
# [25] "Q11_2_12" "Q11_2_99"
samp <- structure(c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), .Dim = c(1L,
26L), .Dimnames = list(NULL, c("Q11_1_1", "Q11_1_2", "Q11_1_3",
"Q11_1_4", "Q11_1_5", "Q11_1_6", "Q11_1_7", "Q11_1_8", "Q11_1_9",
"Q11_1_10", "Q11_1_11", "Q11_1_12", "Q11_1_99", "Q11_2_1", "Q11_2_2",
"Q11_2_3", "Q11_2_4", "Q11_2_5", "Q11_2_6", "Q11_2_7", "Q11_2_8",
"Q11_2_9", "Q11_2_10", "Q11_2_11", "Q11_2_12", "Q11_2_99")))
Upvotes: 1
Reputation: 852
The quickest way I can think of is a combination of strsplit
and paste
:
colnames(samp) <- as.vector(sapply(colnames(samp), function(x){ splitted <- unlist(strsplit(x,"_")) ; paste(splitted[1],splitted[3],splitted[2],sep="_") }))
Upvotes: -1
Reputation: 494
One of the possible solutions.
colconvert <- function(a){
paste0(strsplit(a,"_",fixed = TRUE)[[1]][1],"_",strsplit(a,"_",fixed = TRUE)[[1]][3],"_",strsplit(a,"_",fixed = TRUE)[[1]][2])
}
names(samp) <- lapply(names(samp), colconvert)
Output:
[[1]]
[1] "Q11_1_1"
[[2]]
[1] "Q11_2_1"
[[3]]
[1] "Q11_3_1"
[[4]]
[1] "Q11_4_1"
[[5]]
[1] "Q11_5_1"
Upvotes: 2