df_wide <- tibble(
id = c(1, 2),
sex = c(0, 1),
bp_t1 = c(120, 135),
bp_t2 = c(122, 137),
bp_t3 = c(125, 140)
)
df_long <- df_wide |>
pivot_longer(cols = starts_with("bp"),
names_to = "visit",
values_to = "bp") |>
# build a numeric time index from the visit label:
# gsub("bp_t", "", visit) strips the "bp_t" prefix, leaving "1", "2", "3"
# as.numeric() coerces that text to a number
# - 1 shifts the index so the first visit is baseline = 0
mutate(time = as.numeric(gsub("bp_t", "", visit)) - 1)
df_long