I have a large data set with variables like this:
df <- data.frame(ID=c(1,2),
Height_1=c(180,192),
Weight_1=c(70,90),
Hip_1=c(25,29),
Height_2=c(167,168),
Weight_2=c(50,50),
Hip_2=c(23,27),
Height_3=c(175,176),
Weight_3=c(50,70),
Hip_3=c(28,28))
I would like to order the variables as follows:
ID, Height_1, Height_2, Height_3, Weight_1, Weight_2, Weight_3, Hip_1, Hip_2, Hip_3
I have tried with:
df <- df[sort(names(df))]
But I do not want all the variables alphabetically.
Thank you so much in advance.
CodePudding user response:
An option in base R
would be to convert the column names to a matrix
and then to a vector:
n <- length(unique(sub("_\\d ", "", names(df)[-1])))
df[c('ID', c(matrix(names(df)[-1], ncol = n, byrow = TRUE)))]
Output:
ID Height_1 Height_2 Height_3 Weight_1 Weight_2 Weight_3 Hip_1 Hip_2 Hip_3
1 1 180 167 175 70 50 50 25 23 28
2 2 192 168 176 90 50 70 29 27 28
Or you may use
library(data.table)
library(dplyr)
df %>%
select(ID, order(rowid(readr::parse_number(names(.)[-1]))) 1)
Output:
ID Height_1 Height_2 Height_3 Weight_1 Weight_2 Weight_3 Hip_1 Hip_2 Hip_3
1 1 180 167 175 70 50 50 25 23 28
2 2 192 168 176 90 50 70 29 27 28
CodePudding user response:
This is the long version of @akrun's solution, the core idea is to make pivot longer, transform to factor, and the arrange and pivot back:
library(tidyverse)
df %>%
pivot_longer(-ID) %>%
mutate(helper = str_replace_all(name, "[[:punct:]][0-9] ", ""),
helper = factor(helper, levels = c("Height", "Weight", "Hip"))) %>%
group_by(ID) %>%
arrange(helper, .by_group = TRUE) %>%
select(-helper) %>%
pivot_wider(names_from = name, values_from = value)
ID Height_1 Height_2 Height_3 Weight_1 Weight_2 Weight_3 Hip_1 Hip_2 Hip_3
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 180 167 175 70 50 50 25 23 28
2 2 192 168 176 90 50 70 29 27 28