This is close to a dupe of How to reshape data from long to wide format and Reshape multiple value columns to wide format, though neither answers have multi-column names_from=.
dplyr
This is reshaping from long to wide.
library(dplyr)
library(tidyr)
quux %>%
group_by(PAT_ID) %>%
mutate(rn = row_number()) %>%
ungroup() %>%
pivot_wider(id_cols = PAT_ID, names_from = "rn",
values_from = c("VISIT.DATE", "BP_SYSTOLIC", "BP_DIASTOLIC"),
names_sep = "_") %>%
rename_with(.cols = matches("[0-9]"),
.fn = function(z) case_when(
grepl("VISIT", z) ~ gsub(".*_", "Date_", z),
grepl("SYSTOLIC", z) ~ gsub(".*_", "SBP_", z),
grepl("DIASTOLIC", z) ~ gsub(".*_", "DBP_", z))
)
# # A tibble: 5 × 10
# PAT_ID Date_1 Date_2 Date_3 SBP_1 SBP_2 SBP_3 DBP_1 DBP_2 DBP_3
# <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
# 1 PAT134844 1/2/19 1/4/19 8/8/19 108 125 110 70 71 77
# 2 PAT134845 1/2/19 3/5/19 8/8/19 122 111 135 82 78 68
# 3 PAT122062 1/2/19 6/7/19 NA 126 125 NA 77 61 NA
# 4 PAT134846 1/3/19 4/5/19 6/7/19 125 115 130 85 75 64
# 5 PAT110934 1/3/19 4/5/19 NA 167 120 NA 89 89 NA
data.table
library(data.table)
dcast(as.data.table(quux)[, n := seq(.N), PAT_ID], PAT_ID ~ n, value.var = c("VISIT.DATE", "BP_SYSTOLIC", "BP_DIASTOLIC"))
# PAT_ID VISIT.DATE_1 VISIT.DATE_2 VISIT.DATE_3 BP_SYSTOLIC_1 BP_SYSTOLIC_2 BP_SYSTOLIC_3 BP_DIASTOLIC_1
# <char> <char> <char> <char> <char> <char> <char> <char>
# 1: PAT110934 1/3/19 4/5/19 <NA> 167 120 <NA> 89
# 2: PAT122062 1/2/19 6/7/19 <NA> 126 125 <NA> 77
# 3: PAT134844 1/2/19 1/4/19 8/8/19 108 125 110 70
# 4: PAT134845 1/2/19 3/5/19 8/8/19 122 111 135 82
# 5: PAT134846 1/3/19 4/5/19 6/7/19 125 115 130 85
# 2 variables not shown: [BP_DIASTOLIC_2 <char>, BP_DIASTOLIC_3 <char>]
and you can rename similar to above.
Data
quux <- structure(list(PAT_ID = c("PAT134844", "PAT134845", "PAT122062", "PAT134846", "PAT110934", "PAT134844", "PAT134845", "PAT134846", "PAT110934", "PAT134846", "PAT122062", "PAT134845", "PAT134844"), VISIT.DATE = c("1/2/19", "1/2/19", "1/2/19", "1/3/19", "1/3/19", "1/4/19", "3/5/19", "4/5/19", "4/5/19", "6/7/19", "6/7/19", "8/8/19", "8/8/19"), BP_SYSTOLIC = c("108", "122", "126", "125", "167", "125", "111", "115", "120", "130", "125", "135", "110"), BP_DIASTOLIC = c("70", "82", "77", "85", "89", "71", "78", "75", "89", "64", "61", "68", "77")), class = "data.frame", row.names = c(NA, -13L))