forked from pharmaverse/sdtm.oak
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcal_min_max_date.R
More file actions
129 lines (118 loc) · 4.16 KB
/
Copy pathcal_min_max_date.R
File metadata and controls
129 lines (118 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#' Calculate minimum and maximum date and time in the data frame
#'
#' @description This function derives the earliest/latest date as ISO8601 datetime
#'
#' @param raw_dataset Raw source data frame
#' @param date_variable Single character string. Name of the date variable
#' @param time_variable Single character string. Name of the time variable
#' @param val_type Single character string determining whether to look
#' for the earliest or the latest datetime combination. Permitted values:
#' "min", "max". Default to "min".
#' @param date_format Format of source date variable
#' @param time_format Format of source time variable
#'
#' @return Data frame with 2 columns: unique patient_number and datetime variable
#' column storing the earliest/latest datetime.
#'
#' @export
#' @examples
#' ex_raw <- tibble::tribble(
#' ~patient_number, ~EX_ST_DT, ~EX_ST_TM,
#' "001", "25-04-2022", "10:20",
#' "001", "25-04-2022", "10:15",
#' "001", "25-04-2022", "10:19",
#' "002", "26-05-2022", "UNK:UNK",
#' "002", "26-05-2022", "05:59"
#' )
#'
#' min <- cal_min_max_date(ex_raw,
#' date_variable = "EX_ST_DT",
#' time_variable = "EX_ST_TM",
#' val_type = "min",
#' date_format = "dd-mmm-yyyy",
#' time_format = "H:M"
#' )
#'
#' max <- cal_min_max_date(ex_raw,
#' date_variable = "EX_ST_DT",
#' time_variable = "EX_ST_TM",
#' val_type = "max",
#' date_format = "dd-mmm-yyyy",
#' time_format = "H:M"
#' )
#'
cal_min_max_date <- function(raw_dataset,
date_variable,
time_variable,
val_type = "min",
date_format,
time_format) {
# Check if date parameter is missing or date variable is present in the raw data frame
date_not_in_data <- is.na(date_variable) ||
!utils::hasName(raw_dataset, date_variable)
# Check if time variable is used and present in the raw data frame
time_not_in_data <- !is.na(time_variable) &&
!utils::hasName(raw_dataset, time_variable)
# If date/time variables not present return empty data frame
if (date_not_in_data || time_not_in_data) {
# Return Empty data frame with patient_number and datetime columns
empty_df <- stats::setNames(
data.frame(matrix(ncol = 2L, nrow = 0L)),
c("patient_number", "datetime")
)
cli::cli_warn(paste(
"Date variable", date_variable, "or Time variable", time_variable,
"not present in source data"
))
return(empty_df)
}
fin_df <- raw_dataset
# Time is not used in reference date then use only date
if (is.na(time_variable)) {
fin_df$datetime <- create_iso8601(as.character(raw_dataset[[date_variable]]),
.format = date_format
)
} else {
# If both date and time variables are present use both date and time
raw_dataset$date_time <- paste0(
as.character(raw_dataset[[date_variable]]),
as.character(raw_dataset[[time_variable]])
)
format <- paste0(date_format, time_format)
fin_df$datetime <- as.character(create_iso8601(raw_dataset$date_time,
.format = format,
.na = c(
"UNK", "NA", "U", "unk",
"u", "un", "UN"
)
))
}
fin_df <- fin_df |>
dplyr::select(c("patient_number", "datetime"))
fin_df <- fin_df |>
dplyr::mutate(date_time = datetime) |>
tidyr::separate(
date_time,
sep = "-|T|:",
into = c("year", "month", "day", "hour", "minute"),
fill = "right",
extra = "drop"
) |>
list() |>
stats::setNames("x") |>
with(replace(x, x == "UNK", NA)) |>
list() |>
stats::setNames("x") |>
with(replace(x, x == "", NA))
if (val_type == "min") {
final_df <- fin_df |>
dplyr::arrange(year, month, day, hour, minute)
} else {
final_df <- fin_df |>
dplyr::arrange(dplyr::desc(year), dplyr::desc(month), dplyr::desc(day), dplyr::desc(hour), dplyr::desc(minute))
}
# Keep first appearance in the data frame since it is already sorted
final_df <- final_df[!duplicated(final_df$patient_number), c("patient_number", "datetime")]
final_df <- final_df |> dplyr::filter(!is.na(datetime))
return(final_df)
}