简体   繁体   中英

Stack every other column in R

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.

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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM