Please see a suggestion below
# your data
df <- structure(list(ID = c("A", "B", "C"), pc_2007 = 1:3, pc_2008 = 4:6,
pc_2009 = 7:9, pc_2010 = 10:12, pc_2011 = 13:15, rd_2007 = 16:18,
rd_2008 = 19:21, rd_2009 = 22:24, rd_2010 = 25:27, rd_2011 = 28:30), class = "data.frame", row.names = c(NA,
-3L))
# packages needed
library(dplyr)
library(tidyr)
library(stringr)
# suggestion
df %>%
# your columns names are difficult to work with, I propose you use a "transition" table and use
# regular expressions to select elements you need ...
pivot_longer(cols = 2:last_col(), names_to = "year_code", values_to = "value") %>%
mutate(year = str_extract(year_code, "[0-9]{4}$"),
code = str_extract(year_code, "^[a-z]{2}")) %>%
select(-year_code) %>%
# ...and then pivot your table back
pivot_wider(names_from = code, values_from = value)
Output:
ID year pc rd
<chr> <chr> <int> <int>
1 A 2007 1 16
2 A 2008 4 19
3 A 2009 7 22
4 A 2010 10 25
5 A 2011 13 28
6 B 2007 2 17
7 B 2008 5 20
8 B 2009 8 23
9 B 2010 11 26
10 B 2011 14 29
11 C 2007 3 18
12 C 2008 6 21
13 C 2009 9 24
14 C 2010 12 27
15 C 2011 15 30