Skip to content

Commit

Permalink
Merge pull request #86 from oxford-pharmacoepi/require_funs
Browse files Browse the repository at this point in the history
Require concept and table functions
  • Loading branch information
edward-burn authored Apr 12, 2024
2 parents 44df1fa + 78633a2 commit 2664705
Show file tree
Hide file tree
Showing 16 changed files with 1,040 additions and 583 deletions.
512 changes: 0 additions & 512 deletions .Rhistory

This file was deleted.

7 changes: 7 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,29 @@ export(cohortCodelist)
export(cohortCount)
export(collapseCohort)
export(conceptCohort)
export(endDateColumn)
export(getIdentifier)
export(intersectCohort)
export(joinOverlap)
export(matchCohort)
export(requireAge)
export(requireCohortIntersectFlag)
export(requireConceptIntersectFlag)
export(requireDeathFlag)
export(requireDemographics)
export(requireFutureObservation)
export(requireInDateRange)
export(requirePriorObservation)
export(requireSex)
export(requireTableIntersectFlag)
export(restrictToFirstEntry)
export(settings)
export(splitOverlap)
export(startDateColumn)
export(tableName)
export(trimToDateRange)
importFrom(PatientProfiles,endDateColumn)
importFrom(PatientProfiles,startDateColumn)
importFrom(magrittr,"%>%")
importFrom(omopgenerics,attrition)
importFrom(omopgenerics,cohortCodelist)
Expand Down
8 changes: 8 additions & 0 deletions R/reexports-omopgenerics.R → R/reexports.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ omopgenerics::cohortCodelist
#' @importFrom omopgenerics tableName
#' @export
omopgenerics::tableName

#' @importFrom PatientProfiles startDateColumn
#' @export
PatientProfiles::startDateColumn

#' @importFrom PatientProfiles endDateColumn
#' @export
PatientProfiles::endDateColumn
138 changes: 81 additions & 57 deletions R/requireCohortIntersectFlag.R
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
#' Require cohort subjects are present in another cohort
#'
#' @param x Cohort table.
#' @param targetCohortTable Name of the cohort that we want to check for overlap.
#' @param targetCohortTable Name of the cohort that we want to check for
#' intersect.
#' @param targetCohortId Vector of cohort definition ids to include.
#' @param indexDate Variable in x that contains the date to compute the
#' intersection.
#' @param targetStartDate Date of reference in cohort table, either for start
#' (in overlap) or on its own (for incidence).
#' @param targetEndDate Date of reference in cohort table, either for end
#' (overlap) or NULL (if incidence).
#' @param censorDate Whether to censor overlap events at a specific date or a
#' column date of x.
#' @param window Window to consider events over.
#' @param negate If set as TRUE, criteria will be applied as exclusion
#' rather than inclusion (i.e. require absence in another cohort).
#' @param name Name of the new cohort with the future observation restriction.
#'
#' @return Cohort table with only those in the other cohort kept (or those that
#' are not in the cohort if negate = TRUE)
#'
#' @return Cohort table with only those in the other cohort kept
#' @export
#'
#' @examples
Expand All @@ -31,72 +37,90 @@ requireCohortIntersectFlag <- function(x,
indexDate = "cohort_start_date",
targetStartDate = "cohort_start_date",
targetEndDate = "cohort_end_date",
censorDate = NULL,
window = list(c(0, Inf)),
negate = FALSE){
negate = FALSE,
name = omopgenerics::tableName(x)){
# checks
assertCharacter(name, length = 1)
assertLogical(negate, length = 1)
validateCohortTable(x)
cdm <- omopgenerics::cdmReference(x)
validateCDM(cdm)
validateIndexDate(indexDate, x)

cols <- unique(c("cohort_definition_id", "subject_id",
"cohort_start_date", "cohort_end_date",
indexDate))
cols <- unique(c("cohort_definition_id", "subject_id",
"cohort_start_date", "cohort_end_date",
indexDate))

if(is.list(window)){
window_start <- window[[1]][1]
window_end <- window[[1]][2]
} else {
window_start <- window[1]
window_end <- window[2]
}
if(is.list(window)){
window_start <- window[[1]][1]
window_end <- window[[1]][2]
} else {
window_start <- window[1]
window_end <- window[2]
}

cdm <- attr(x, "cdm_reference")
cdm <- omopgenerics::cdmReference(x)

if(is.null(cdm[[targetCohortTable]])){
cli::cli_abort("targetCohortTable not found in cdm reference")
}
if(is.null(cdm[[targetCohortTable]])){
cli::cli_abort("targetCohortTable not found in cdm reference")
}

if(is.null(targetCohortId)){
targetCohortId <- CDMConnector::settings(cdm[[targetCohortTable]]) %>%
dplyr::pull("cohort_definition_id")
}
if(is.null(targetCohortId)){
targetCohortId <- CDMConnector::settings(cdm[[targetCohortTable]]) %>%
dplyr::pull("cohort_definition_id")
}

if(length(targetCohortId) > 1){
cli::cli_abort("Only one target cohort is currently supported")
}
if(length(targetCohortId) > 1){
cli::cli_abort("Only one target cohort is currently supported")
}

target_name <- cdm[[targetCohortTable]] %>%
omopgenerics::settings() %>%
dplyr::filter(.data$cohort_definition_id == .env$targetCohortId) %>%
dplyr::pull("cohort_name")
target_name <- cdm[[targetCohortTable]] %>%
omopgenerics::settings() %>%
dplyr::filter(.data$cohort_definition_id == .env$targetCohortId) %>%
dplyr::pull("cohort_name")

subsetCohort <- x %>%
dplyr::select(dplyr::all_of(.env$cols)) %>%
PatientProfiles::addCohortIntersectFlag(
targetCohortTable = targetCohortTable,
targetCohortId = targetCohortId,
indexDate = indexDate,
targetStartDate = targetStartDate,
targetEndDate = targetEndDate,
window = window,
nameStyle = "intersect_cohort"
)
subsetCohort <- x %>%
dplyr::select(dplyr::all_of(.env$cols)) %>%
PatientProfiles::addCohortIntersectFlag(
targetCohortTable = targetCohortTable,
targetCohortId = targetCohortId,
indexDate = indexDate,
targetStartDate = targetStartDate,
targetEndDate = targetEndDate,
window = window,
censorDate = censorDate,
nameStyle = "intersect_cohort"
)

if(isFALSE(negate)){
subsetCohort <- subsetCohort %>%
dplyr::filter(.data$intersect_cohort == 1) %>%
dplyr::select(!"intersect_cohort")
} else {
# ie require absence instead of presence
subsetCohort <- subsetCohort %>%
dplyr::filter(.data$intersect_cohort != 1) %>%
dplyr::select(!"intersect_cohort")
}
if(isFALSE(negate)){
subsetCohort <- subsetCohort %>%
dplyr::filter(.data$intersect_cohort == 1) %>%
dplyr::select(!"intersect_cohort")
# attrition reason
reason <- glue::glue("In cohort {target_name} between {window_start} & ",
"{window_end} days relative to {indexDate}")
} else {
# ie require absence instead of presence
subsetCohort <- subsetCohort %>%
dplyr::filter(.data$intersect_cohort != 1) %>%
dplyr::select(!"intersect_cohort")
# attrition reason
reason <- glue::glue("Not in cohort {target_name} between {window_start} & ",
"{window_end} days relative to {indexDate}")
}

if (!is.null(censorDate)) {
reason <- glue::glue("{reason}, censoring at {censorDate}")
}

x %>%
dplyr::inner_join(subsetCohort,
by = c(cols)) %>%
CDMConnector::recordCohortAttrition(reason =
glue::glue("In cohort {target_name} between ",
"{window_start} & ",
"{window_end} days relative to ",
"{indexDate}"))
x <- x %>%
dplyr::inner_join(subsetCohort,
by = c(cols)) %>%
dplyr::compute(name = name, temporary = FALSE) %>%
CDMConnector::recordCohortAttrition(reason = reason)

return(x)
}

119 changes: 119 additions & 0 deletions R/requireConceptIntersectFlag.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#' Require cohort subjects to have events of a concept list
#'
#' @param x Cohort table.
#' @param conceptSet Concept set list.
#' @param indexDate Variable in x that contains the date to compute the
#' intersection.
#' @param targetStartDate Date of reference in cohort table, either for start
#' (in overlap) or on its own (for incidence).
#' @param targetEndDate Date of reference in cohort table, either for end
#' (overlap) or NULL (if incidence).
#' @param censorDate Whether to censor overlap events at a specific date or a
#' column date of x.
#' @param window Window to consider events over.
#' @param negate If set as TRUE, criteria will be applied as exclusion
#' rather than inclusion (i.e. require absence in another cohort).
#' @param name Name of the new cohort with the future observation restriction.
#'
#' @return Cohort table with only those with the events in the concept list
#' kept (or those without the event if nagate = TRUE)
#'
#' @export
#'
#' @examples
#' library(PatientProfiles)
#' library(CohortConstructor)
#' cdm <- mockPatientProfiles()
#' cdm <- CDMConnector::insertTable(cdm, name = "concept",
#' table = dplyr::tibble(
#' "concept_id" = 1,
#' "concept_name" = "my concept",
#' "domain_id" = "Drug",
#' "vocabulary_id" = NA,
#' "concept_class_id" = NA,
#' "concept_code" = NA,
#' "valid_start_date" = NA,
#' "valid_end_date" = NA
#' ))
#' cdm$cohort2 <- requireConceptIntersectFlag(
#' x = cdm$cohort1,
#' conceptSet = list(a = 1),
#' window = c(-Inf, 0),
#' name = "cohort2")
requireConceptIntersectFlag <- function(x,
conceptSet,
indexDate = "cohort_start_date",
targetStartDate = "event_start_date",
targetEndDate = "event_end_date",
censorDate = NULL,
window = list(c(0, Inf)),
negate = FALSE,
name = omopgenerics::tableName(x)){
# checks
assertCharacter(name, length = 1)
assertLogical(negate, length = 1)
validateCohortTable(x)
cdm <- omopgenerics::cdmReference(x)
validateCDM(cdm)
validateIndexDate(indexDate, x)
assertList(conceptSet)

cols <- unique(c("cohort_definition_id", "subject_id",
"cohort_start_date", "cohort_end_date",
indexDate))

if(is.list(window)){
window_start <- window[[1]][1]
window_end <- window[[1]][2]
} else {
window_start <- window[1]
window_end <- window[2]
}

if (length(conceptSet) > 1) {
cli::cli_abort("We currently suport 1 concept set.")
}

cdm <- omopgenerics::cdmReference(x)

subsetCohort <- x %>%
dplyr::select(dplyr::all_of(.env$cols)) %>%
PatientProfiles::addConceptIntersectFlag(
conceptSet = conceptSet,
indexDate = indexDate,
targetStartDate = targetStartDate,
targetEndDate = targetEndDate,
window = window,
censorDate = censorDate,
nameStyle = "intersect_concept"
)

if(isFALSE(negate)){
subsetCohort <- subsetCohort %>%
dplyr::filter(.data$intersect_concept == 1) %>%
dplyr::select(!"intersect_concept")
# attrition reason
reason <- glue::glue("Concept {names(conceptSet)} between {window_start} & ",
"{window_end} days relative to {indexDate}")
} else {
# ie require absence instead of presence
subsetCohort <- subsetCohort %>%
dplyr::filter(.data$intersect_concept != 1) %>%
dplyr::select(!"intersect_concept")
# attrition reason
reason <- glue::glue("Not in concept {names(conceptSet)} between {window_start} & ",
"{window_end} days relative to {indexDate}")
}

if (!is.null(censorDate)) {
reason <- glue::glue("{reason}, censoring at {censorDate}")
}

x <- x %>%
dplyr::inner_join(subsetCohort,
by = c(cols)) %>%
dplyr::compute(name = name, temporary = FALSE) %>%
CDMConnector::recordCohortAttrition(reason = reason)

return(x)
}
Loading

0 comments on commit 2664705

Please sign in to comment.