I'm looking to stack every other column under the previous column in R. Any suggestions?
For example:
c1 | c2 | c3 | c4 |
---|---|---|---|
A | 1 | D | 4 |
B | 2 | E | 5 |
C | 3 | F | 6 |
dat <- data.frame(
c1 = c("A", "B", "C"),
c2 = c(1, 2, 3),
c3 = c("D", "E", "F"),
c4 = c(4, 5, 6))
To look like this:
c1 | c2 |
---|---|
A | D |
1 | 4 |
B | E |
2 | 5 |
C | F |
3 | 6 |
dat2 <- data.frame(
c1 = c("A", 1, "B", 2, "C", 3),
c2 = c("D", 4, "E", 5, "F", 6))
Thanks in advance.
CodePudding user response:
For an even numbered number of columns you can do something like:
do.call(cbind, lapply(seq(length(dat)/2), \(x) stack(dat[ ,x ((x-1):x)])[1])) |>
set_names(names(dat)[seq(length(dat)/2)])
c1 c2
1 A D
2 B E
3 C F
4 1 4
5 2 5
6 3 6
This gets the first column when calling stack
and cbinds
all the stacked columns.
CodePudding user response:
A basic way with stack()
:
as.data.frame(sapply(seq(1, ncol(dat), 2), \(x) stack(dat[x:(x 1)])[[1]]))
# V1 V2
# 1 A D
# 2 B E
# 3 C F
# 4 1 4
# 5 2 5
# 6 3 6
You could also rename the data with a structural foramt and pass it into tidyr::pivot_longer()
:
library(dplyr)
library(tidyr)
dat %>%
rename_with(~ paste0('c', ceiling(seq_along(.x) / 2), '_', 1:2)) %>%
mutate(across(, as.character)) %>%
pivot_longer(everything(), names_to = c(".value", NA), names_sep = '_')
# # A tibble: 6 × 2
# c1 c2
# <chr> <chr>
# 1 A D
# 2 1 4
# 3 B E
# 4 2 5
# 5 C F
# 6 3 6
The rename
line transforms c1 - c4
to c1_1, c1_2, c2_1, c2_2
.