Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 20f016c

Browse files
committedDec 27, 2023
updates
1 parent f3233f3 commit 20f016c

24 files changed

+343
-37
lines changed
 

‎NAMESPACE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Generated by roxygen2: do not edit by hand
22

3-
export(generateCombinationCohortSet)
3+
export(generateIntersectCohortSet)
44
export(generateMatchedCohortSet)
55
export(getIdentifier)
66
export(joinOverlap)

‎R/generateCombinationCohorts.R ‎R/generateIntersectCohorts.R

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#'
2121
#' cdm <- mockPatientProfiles()
2222
#'
23-
#' cdm <- generateCombinationCohortSet(
23+
#' cdm <- generateIntersectCohortSet(
2424
#' cdm = cdm,
2525
#' name = "cohort3",
2626
#' targetCohortName = "cohort2"
@@ -32,7 +32,7 @@
3232
#'
3333
#' }
3434

35-
generateCombinationCohortSet <- function(cdm,
35+
generateIntersectCohortSet <- function(cdm,
3636
name,
3737
targetCohortName,
3838
targetCohortId = NULL,

‎R/generateUnionCohortSet.R

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
generateUnionCohortSet <- function(){
3+
4+
}

‎R/requireCohortIntersectFlag.R

+26-5
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,30 @@
1111
#' (in overlap) or on its own (for incidence)
1212
#' @param targetEndDate date of reference in cohort table, either for end
1313
#' (overlap) or NULL (if incidence)
14-
#' @param window window to consider events of
14+
#' @param window window to consider events over
15+
#' @param negate If set as TRUE, criteria will be applied as exclusion
16+
#' rather than inclusion (i.e. require absence in another cohort)
1517
#'
1618
#' @return Cohort table with only those in the other cohort kept
1719
#' @export
1820
#'
1921
#' @examples
22+
#' library(DrugUtilisation)
23+
#' library(CohortConstructor)
24+
#' cdm <- mockDrugUtilisation(numberIndividuals = 100)
25+
#' cdm$cohort1 %>%
26+
#' requireCohortIntersectFlag(targetCohortTable = "cohort2",
27+
#' targetCohortId = 1,
28+
#' indexDate = "cohort_start_date",
29+
#' window = c(-Inf, 0))
2030
requireCohortIntersectFlag <- function(x,
2131
targetCohortTable,
2232
targetCohortId = NULL,
2333
indexDate = "cohort_start_date",
2434
targetStartDate = "cohort_start_date",
2535
targetEndDate = "cohort_end_date",
26-
window = list(c(0, Inf))){
36+
window = list(c(0, Inf)),
37+
negate = FALSE){
2738

2839
cols <- unique(c("cohort_definition_id", "subject_id",
2940
"cohort_start_date", "cohort_end_date",
@@ -67,9 +78,19 @@ subsetCohort <- x %>%
6778
targetEndDate = targetEndDate,
6879
window = window,
6980
nameStyle = "intersect_cohort"
70-
) %>%
71-
dplyr::filter(.data$intersect_cohort == 1) %>%
72-
dplyr::select(!"intersect_cohort")
81+
)
82+
83+
if(isFALSE(negate)){
84+
subsetCohort <- subsetCohort %>%
85+
dplyr::filter(.data$intersect_cohort == 1) %>%
86+
dplyr::select(!"intersect_cohort")
87+
} else {
88+
# ie require absence instead of presence
89+
subsetCohort <- subsetCohort %>%
90+
dplyr::filter(.data$intersect_cohort != 1) %>%
91+
dplyr::select(!"intersect_cohort")
92+
}
93+
7394

7495
x %>%
7596
dplyr::inner_join(subsetCohort,

‎R/requireDateRange.R

+19-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
#' @export
1111
#'
1212
#' @examples
13+
#' library(DrugUtilisation)
14+
#' library(CohortConstructor)
15+
#' cdm <- mockDrugUtilisation(numberIndividuals = 100)
16+
#' cdm$cohort1 %>%
17+
#' requireInDateRange(indexDate = "cohort_start_date",
18+
#' dateRange = as.Date(c("2010-01-01", "2019-01-01")))
1319
requireInDateRange <- function(cohort,
1420
indexDate = "cohort_start_date",
1521
dateRange = as.Date(c(NA, NA))) {
@@ -38,10 +44,20 @@ requireInDateRange <- function(cohort,
3844
#' @param dateRange A window of time during which the index date must have
3945
#' been observed
4046
#'
41-
#' @return
47+
#' @return The cohort table with record timings updated to only be within the
48+
#' date range. Any records with all time outside of the range will have
49+
#' been dropped.
4250
#' @export
4351
#'
4452
#' @examples
53+
#' library(DrugUtilisation)
54+
#' library(CohortConstructor)
55+
#' cdm <- mockDrugUtilisation(numberIndividuals = 100)
56+
#' cdm$cohort1 %>%
57+
#' trimToDateRange(startDate = "cohort_start_date",
58+
#' endDate = "cohort_end_date",
59+
#' dateRange = as.Date(c("2015-01-01",
60+
#' "2015-12-31")))
4561
trimToDateRange <- function(cohort,
4662
startDate = "cohort_start_date",
4763
endDate = "cohort_end_date",
@@ -93,6 +109,8 @@ trimToDateRange <- function(cohort,
93109
endDate,
94110
" <= ", dateRange[2]
95111
))
112+
113+
cohort
96114
}
97115

98116
trimStartDate <- function(cohort,

‎R/requireDemographics.R

+43-5
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,20 @@
1313
#' @param minFutureObservation A minimum number of future observation days in
1414
#' the database.
1515
#'
16-
#' @return
16+
#' @return The cohort table with only records for individuals satisfying the
17+
#' demographic requirements
1718
#' @export
1819
#'
1920
#' @examples
21+
#' library(DrugUtilisation)
22+
#' library(CohortConstructor)
23+
#' cdm <- mockDrugUtilisation(numberIndividuals = 100)
24+
#' cdm$cohort1 %>%
25+
#' requireDemographics(indexDate = "cohort_start_date",
26+
#' ageRange = list(c(18, 65)),
27+
#' sex = "Female",
28+
#' minPriorObservation = 365)
29+
#'
2030
requireDemographics <- function(cohort,
2131
indexDate = "cohort_start_date",
2232
ageRange = list(c(0, 150)),
@@ -63,10 +73,17 @@ requireDemographics <- function(cohort,
6373
#' demographics characteristics on which to restrict on.
6474
#' @param ageRange A list of minimum and maximum age
6575
#'
66-
#' @return
76+
#' @return The cohort table with only records for individuals satisfying the
77+
#' age requirement
6778
#' @export
6879
#'
6980
#' @examples
81+
#' library(DrugUtilisation)
82+
#' library(CohortConstructor)
83+
#' cdm <- mockDrugUtilisation(numberIndividuals = 100)
84+
#' cdm$cohort1 %>%
85+
#' requireAge(indexDate = "cohort_start_date",
86+
#' ageRange = list(c(18, 65)))
7087
requireAge <- function(cohort,
7188
indexDate = "cohort_start_date",
7289
ageRange = list(c(0, 150))) {
@@ -94,10 +111,16 @@ requireAge <- function(cohort,
94111
#' @param sex Can be "Both", "Male" or "Female". If one of the latter, only
95112
#' those with that sex will be included.
96113
#'
97-
#' @return
114+
#' @return The cohort table with only records for individuals satisfying the
115+
#' sex requirement
98116
#' @export
99117
#'
100118
#' @examples
119+
#' library(DrugUtilisation)
120+
#' library(CohortConstructor)
121+
#' cdm <- mockDrugUtilisation(numberIndividuals = 100)
122+
#' cdm$cohort1 %>%
123+
#' requireSex(sex = "Female")
101124
requireSex <- function(cohort,
102125
sex = c("Both")) {
103126
cohort <- demographicsFilter(
@@ -127,10 +150,17 @@ requireSex <- function(cohort,
127150
#' @param minPriorObservation A mimimum number of prior observation days in
128151
#' the database.
129152
#'
130-
#' @return
153+
#' @return The cohort table with only records for individuals satisfying the
154+
#' prior observation requirement
131155
#' @export
132156
#'
133157
#' @examples
158+
#' library(DrugUtilisation)
159+
#' library(CohortConstructor)
160+
#' cdm <- mockDrugUtilisation(numberIndividuals = 100)
161+
#' cdm$cohort1 %>%
162+
#' requirePriorObservation(indexDate = "cohort_start_date",
163+
#' minPriorObservation = 365)
134164
requirePriorObservation <- function(cohort,
135165
indexDate = "cohort_start_date",
136166
minPriorObservation = 0) {
@@ -160,10 +190,18 @@ requirePriorObservation <- function(cohort,
160190
#' @param minFutureObservation A minimum number of future observation days in
161191
#' the database.
162192
#'
163-
#' @return
193+
#' @return The cohort table with only records for individuals satisfying the
194+
#' future observation requirement
195+
#'
164196
#' @export
165197
#'
166198
#' @examples
199+
#' library(DrugUtilisation)
200+
#' library(CohortConstructor)
201+
#' cdm <- mockDrugUtilisation(numberIndividuals = 100)
202+
#' cdm$cohort1 %>%
203+
#' requireFutureObservation(indexDate = "cohort_start_date",
204+
#' minFutureObservation = 30)
167205
requireFutureObservation <- function(cohort,
168206
indexDate = "cohort_start_date",
169207
minFutureObservation = 0) {

‎R/restrictToFirstEntry.R

+5-4
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ restrictToFirstEntry <- function(cohort,
3030
#restrict to first entry
3131
indexDateSym <- rlang::sym(indexDate)
3232

33-
cohort <- cohort |> dplyr::group_by(.data$subject_id,.data$cohort_definition_id) |>
34-
dplyr::filter(!!indexDateSym == min(!!indexDateSym, na.rm = TRUE)) |>
35-
dplyr::ungroup() |>
36-
CDMConnector::recordCohortAttrition("restrict to first entry")
33+
cohort <- cohort %>%
34+
dplyr::group_by(.data$subject_id,.data$cohort_definition_id) %>%
35+
dplyr::filter(!!indexDateSym == min(!!indexDateSym, na.rm = TRUE)) %>%
36+
dplyr::ungroup() %>%
37+
CDMConnector::recordCohortAttrition("Restricted to first entry")
3738

3839
return(cohort)
3940

‎README.Rmd

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ Both diclofenac and acetaminophen
130130
Generate a combination cohort.
131131

132132
```{r}
133-
cdm <- generateCombinationCohortSet(cdm = cdm,
133+
cdm <- generateIntersectCohortSet(cdm = cdm,
134134
name = "combinations",
135135
targetCohortName = "medications")
136136

‎man/generateCombinationCohortSet.Rd ‎man/generateIntersectCohortSet.Rd

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/getIdentifier.Rd

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/joinOverlap.Rd

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/requireAge.Rd

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/requireCohortIntersectFlag.Rd

+16-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/requireDemographics.Rd

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/requireFutureObservation.Rd

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/requireInDateRange.Rd

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/requirePriorObservation.Rd

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/requireSex.Rd

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/splitOverlap.Rd

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/trimToDateRange.Rd

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎tests/testthat/test-generateCombinationCohorts.R ‎tests/testthat/test-generateIntersectCohorts.R

+5-5
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ test_that("splitOverlap", {
123123
DBI::dbDisconnect(db, shutdown = TRUE)
124124
})
125125

126-
test_that("generateCombinationCohortSet", {
126+
test_that("generateIntersectCohortSet", {
127127
cohort <- dplyr::tibble(
128128
cohort_definition_id = c(1, 2, 3, 1, 2, 3, 1, 2),
129129
subject_id = c(1, 1, 1, 2, 3, 3, 4, 4),
@@ -154,7 +154,7 @@ test_that("generateCombinationCohortSet", {
154154
)
155155

156156
# mutually exclusive
157-
expect_no_error(cdm <- generateCombinationCohortSet(
157+
expect_no_error(cdm <- generateIntersectCohortSet(
158158
cdm = cdm, name = "cohort2", targetCohortName = "cohort1",
159159
mutuallyExclusive = TRUE
160160
))
@@ -167,7 +167,7 @@ test_that("generateCombinationCohortSet", {
167167
))
168168

169169
# not mutually exclusive
170-
expect_no_error(cdm <- generateCombinationCohortSet(
170+
expect_no_error(cdm <- generateIntersectCohortSet(
171171
cdm = cdm, name = "cohort3", targetCohortName = "cohort1",
172172
mutuallyExclusive = FALSE
173173
))
@@ -180,7 +180,7 @@ test_that("generateCombinationCohortSet", {
180180
))
181181

182182
# not enough cohorts provided
183-
expect_warning(cdm <- generateCombinationCohortSet(
183+
expect_warning(cdm <- generateIntersectCohortSet(
184184
cdm = cdm, name = "cohort4", targetCohortName = "cohort1",
185185
targetCohortId = 1
186186
))
@@ -219,7 +219,7 @@ test_that("only return comb", {
219219
observation_period = observation_period, person = person, cohort1 = cohort
220220
)
221221

222-
cdm <- generateCombinationCohortSet(
222+
cdm <- generateIntersectCohortSet(
223223
cdm = cdm, name = "cohort2", targetCohortName = "cohort1",
224224
mutuallyExclusive = FALSE, returnOnlyComb = TRUE
225225
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
test_that("multiplication works", {
2+
expect_equal(2 * 2, 4)
3+
})

‎tests/testthat/test-requireCohortIntersectFlag.R

+25
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,29 @@ test_that("requiring presence in another cohort", {
5454

5555
})
5656

57+
test_that("requiring absence in another cohort", {
5758

59+
cdm <- PatientProfiles::mockPatientProfiles(patient_size = 100,
60+
drug_exposure_size = 100)
61+
62+
cdm$cohort3_inclusion <- requireCohortIntersectFlag(x = cdm$cohort1,
63+
targetCohortTable = "cohort2",
64+
targetCohortId = 1,
65+
window = c(-Inf, Inf))
66+
cdm$cohort3_exclusion <- requireCohortIntersectFlag(x = cdm$cohort1,
67+
targetCohortTable = "cohort2",
68+
targetCohortId = 1,
69+
window = c(-Inf, Inf),
70+
negate = TRUE)
71+
72+
in_both <- intersect(cdm$cohort3_inclusion %>%
73+
dplyr::pull("subject_id") %>%
74+
unique(),
75+
cdm$cohort3_exclusion %>%
76+
dplyr::pull("subject_id") %>%
77+
unique())
78+
expect_true(length(in_both) == 0)
79+
80+
CDMConnector::cdm_disconnect(cdm)
81+
82+
})
+100-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "a02_applying_cohort_restrictions"
2+
title: "Applying cohort restrictions"
33
output: rmarkdown::html_vignette
44
vignette: >
55
%\VignetteIndexEntry{a02_applying_cohort_restrictions}
@@ -9,11 +9,108 @@ vignette: >
99

1010
```{r, include = FALSE}
1111
knitr::opts_chunk$set(
12-
collapse = TRUE,
12+
collapse = TRUE,
13+
message = FALSE,
14+
warning = FALSE,
1315
comment = "#>"
1416
)
1517
```
1618

17-
```{r setup}
19+
For this example we'll use the Eunomia synthetic data from the CDMConnector package.
20+
```{r}
21+
library(CDMConnector)
22+
library(DrugUtilisation)
1823
library(CohortConstructor)
24+
con <- DBI::dbConnect(duckdb::duckdb(), dbdir = eunomia_dir())
25+
cdm <- cdm_from_con(con, cdm_schema = "main",
26+
write_schema = c(prefix = "my_study_", schema = "main"))
1927
```
28+
29+
Let's start by creating two drug cohorts, one for users of diclofenac and another for users of acetaminophen. We'll use the `generateDrugUtilisationCohortSet()` from the DrugUtilisation package so that we can specify a gap era when creating the cohort.
30+
```{r}
31+
cdm <- generateDrugUtilisationCohortSet(cdm = cdm,
32+
name = "medications",
33+
conceptSet = list("diclofenac" = 1124300,
34+
"acetaminophen" = 1127433),
35+
gapEra = 7)
36+
cohortCount(cdm$medications)
37+
```
38+
39+
As well as our medication cohorts, let's also make another cohort containing individuals with a record of a GI bleed. For this cohort we can use `generateConceptCohortSet()` from the CDMConnector package. Later we'll use this cohort when specifying inclusion/ exclusion criteria.
40+
```{r}
41+
cdm <- generateConceptCohortSet(cdm = cdm,
42+
name = "gi_bleed",
43+
conceptSet = list("gi_bleed" = 192671))
44+
```
45+
46+
## Keep only the first record per person
47+
Individuals can contribute multiple records per cohort. However now we'll keep only their earliest cohort entry of the remaining records using `restrictToFirstEntry()` from CohortConstructor. We can see that after this we have one record per person for each cohort.
48+
```{r}
49+
cdm$medications <- cdm$medications %>%
50+
restrictToFirstEntry(indexDate = "cohort_start_date")
51+
52+
cohortCount(cdm$medications)
53+
```
54+
55+
Note, applying this criteria later after applying other criteria would result in a different result. Here we're requiring that individuals meet inclusion criteria at the time of their first use of diclofenac or acetaminophen.
56+
57+
## Applying restrictions on patient demographics
58+
Using `requireDemographics()` we'll require that individuals in our medications cohort are female and, relative to their cohort start date, are between 18 and 85 with at least 30 days of prior observation time in the database.
59+
```{r}
60+
cdm$medications <- cdm$medications %>%
61+
requireDemographics(indexDate = "cohort_start_date",
62+
ageRange = list(c(18, 85)),
63+
sex = "Female",
64+
minPriorObservation = 30)
65+
```
66+
67+
We can then see how many people have people have been excluded based on these demographic requirements.
68+
```{r}
69+
cohort_attrition(cdm$medications) %>%
70+
dplyr::filter(reason == "Demographic requirements") %>%
71+
dplyr::glimpse()
72+
```
73+
74+
75+
## Restrictions on calendar dates
76+
Next we can use `requireInDateRange()` to keep only those records where cohort entry was between a particular date range.
77+
```{r}
78+
cdm$medications <- cdm$medications %>%
79+
requireInDateRange(indexDate = "cohort_start_date",
80+
dateRange = as.Date(c("2000-01-01", "2015-01-01")))
81+
```
82+
83+
Again, we can track cohort attrition
84+
```{r}
85+
cohort_attrition(cdm$medications) %>%
86+
dplyr::filter(reason == "cohort_start_date between 2000-01-01 and 2015-01-01") %>%
87+
dplyr::glimpse()
88+
```
89+
90+
91+
## Restrictions on cohort presence
92+
We could require that individuals in our medication cohorts have a history of GI bleed. To do this we can use the `requireCohortIntersectFlag()` function.
93+
94+
```{r}
95+
cdm$medications_gi_bleed <- cdm$medications %>%
96+
requireCohortIntersectFlag(targetCohortTable = "gi_bleed",
97+
targetCohortId = 1,
98+
indexDate = "cohort_start_date",
99+
window = c(-Inf, 0))
100+
cohort_count(cdm$medications_gi_bleed)
101+
```
102+
103+
Instead of requiring that individuals have history of GI bleed, we could instead require that they are don't have any history of it. In this case we can again use the `requireCohortIntersectFlag()` function, but this time set the negate argument to FALSE to require individuals' absence in this other cohort rather than their presence in it.
104+
105+
```{r}
106+
cdm$medications_no_gi_bleed <- cdm$medications %>%
107+
requireCohortIntersectFlag(targetCohortTable = "gi_bleed",
108+
targetCohortId = 1,
109+
indexDate = "cohort_start_date",
110+
window = c(-Inf, 0),
111+
negate = TRUE)
112+
cohort_count(cdm$medications_no_gi_bleed)
113+
```
114+
115+
116+

0 commit comments

Comments
 (0)
Please sign in to comment.