I would to reverse the reshaping from wide back to long format but am stack how I should proceed so that the values for a1_* be placed in a1. Is there a workaround this?
library(tidyverse)
df <- tibble(
id = c("s001", "s002", "s002", "s003", "s003",
"s004", "s005"),
a1 = c("A", "B", "C", "A", "D", "A", "B"),
a2 = c(23, 24, 45, 23, 56, 45, 34),
a3 = c("Primary", "Secondary", "Tertiary", "Primary",
"Tertiary", "Secondary", "Primary"))
#---- Reshape long to wide
df <- df %>%
group_by(id) %>%
mutate(index = row_number()) %>% ungroup()
df_wide <- df %>%
pivot_wider(id_cols = id,
names_from = index,
values_from = starts_with("a"))
#---- Reverse back
df_long <- df_wide %>%
pivot_longer(!id,
names_to = "index",
names_prefix = "a\\d_"
)
CodePudding user response:
What you need to do is specify that you are using the specific values on the left hand of the separator to identify unique columns (i.e. a1, ...) and on the right index.
We can use the names_sep argument for this, and values_drop_na to remove rows that weren't in the original df.
df_wide %>%
pivot_longer(!id,
names_to = c(".value", "index"),
names_sep = "_",
values_drop_na = T)
#> # A tibble: 7 × 5
#> id index a1 a2 a3
#> <chr> <chr> <chr> <dbl> <chr>
#> 1 s001 1 A 23 Primary
#> 2 s002 1 B 24 Secondary
#> 3 s002 2 C 45 Tertiary
#> 4 s003 1 A 23 Primary
#> 5 s003 2 D 56 Tertiary
#> 6 s004 1 A 45 Secondary
#> 7 s005 1 B 34 Primary
