Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICD conflict rules #4

Open
andrewallenbruce opened this issue Apr 4, 2024 · 2 comments
Open

ICD conflict rules #4

andrewallenbruce opened this issue Apr 4, 2024 · 2 comments
Assignees
Labels
enhancement New feature or request

Comments

@andrewallenbruce
Copy link
Owner

andrewallenbruce commented Apr 4, 2024

@andrewallenbruce andrewallenbruce self-assigned this Apr 4, 2024
@andrewallenbruce andrewallenbruce added the enhancement New feature or request label Apr 4, 2024
@andrewallenbruce
Copy link
Owner Author

library(tidyverse)
library(pathologie)
library(vctrs)

years_floor <- function(from = lubridate::today() - 1052,
                        to   = lubridate::today()) {
  floor(
    as.double(
      difftime(
        to,
        from,
        units = "weeks",
        tz = "UTC"
        )
      ) / 52.17857
    )
}

years_floor()
#> [1] 2

apply_age_edits <- function(df) {
  dplyr::mutate(
    df,
    conflict = dplyr::if_else(
      icd_limitation == "Perinatal/Newborn (Age 0 Only)" &
        age != 0,
      "Conflict",
      NA_character_
    ),
    conflict = dplyr::if_else(
      icd_limitation == "Pediatric (Ages 0-17)" &
        dplyr::between(age, 0, 17) == FALSE,
      "Conflict",
      NA_character_
    ),
    conflict = dplyr::if_else(
      icd_limitation == "Maternity (Ages 9-64)" &
        dplyr::between(age, 9, 64) == FALSE,
      "Conflict",
      NA_character_
    ),
    conflict = dplyr::if_else(
      icd_limitation == "Adult (Ages 15-124)" &
        dplyr::between(age, 15, 124) == FALSE,
      "Conflict",
      NA_character_
    )
  )
}

age_icds <- vctrs::vec_c(
  "F53.0",
  "F64.2",
  "F32.81",
  "Z62.21",
  "O90.6",
  "F03.90",
  "Q96.8",
  "Z00.00",
  "Z91.82",
  "G32.81",
  "T76.02XA"
)

age_example <- readr::read_csv(
    file, 
    show_col_types = FALSE) |>
  dplyr::select(
    dob      = patient_dob,
    dos      = cpt_dos,
    icd_code = diagnosis) |>
  tidyr::separate_longer_delim(
    cols  = icd_code,
    delim = ",") |>
  dplyr::filter(icd_code %in% age_icds)

age_example
#> # A tibble: 299 × 3
#>    dob        dos        icd_code
#>    <date>     <date>     <chr>   
#>  1 2015-11-27 2023-01-08 Z00.00  
#>  2 2010-02-02 2024-02-05 F32.81  
#>  3 1990-11-07 2023-11-13 F53.0   
#>  4 2006-12-23 2023-09-26 F64.2   
#>  5 1993-05-30 2023-08-07 Q96.8   
#>  6 1986-01-25 2023-08-05 Z91.82  
#>  7 1992-10-23 2023-06-29 O90.6   
#>  8 2014-01-25 2023-06-27 Z00.00  
#>  9 2011-01-07 2023-04-12 F64.2   
#> 10 1992-12-03 2023-03-02 F53.0   
#> # ℹ 289 more rows

edits <- pathologie::search_edits() |>
  dplyr::select(
    icd_code        = code,
    icd_description = description,
    icd_limitation  = category
  ) |>
  dplyr::mutate(
    icd_conflict = dplyr::case_match(
      icd_limitation,
      c(
        "Perinatal/Newborn (Age 0 Only)",
        "Pediatric (Ages 0-17)",
        "Maternity (Ages 9-64)",
        "Adult (Ages 15-124)"
      ) ~ "Age",
      c("Female Only", "Male Only") ~ "Sex",
      .default = "Other"
    ),
    .before = icd_limitation
  )

edits
#> # A tibble: 7,946 × 4
#>    icd_code icd_description                          icd_conflict icd_limitation
#>    <chr>    <chr>                                    <chr>        <chr>         
#>  1 A33      Tetanus neonatorum                       Age          Perinatal/New…
#>  2 E84.11   Meconium ileus in cystic fibrosis        Age          Perinatal/New…
#>  3 H04.531  Neonatal obstruction of right nasolacri… Age          Perinatal/New…
#>  4 H04.532  Neonatal obstruction of left nasolacrim… Age          Perinatal/New…
#>  5 H04.533  Neonatal obstruction of bilateral nasol… Age          Perinatal/New…
#>  6 H04.539  Neonatal obstruction of unspecified nas… Age          Perinatal/New…
#>  7 N47.0    Adherent prepuce, newborn                Age          Perinatal/New…
#>  8 Z00.110  Health examination for newborn under 8 … Age          Perinatal/New…
#>  9 Z00.111  Health examination for newborn 8 to 28 … Age          Perinatal/New…
#> 10 Z05.0    Obs & eval of NB for suspected cardiac … Age          Perinatal/New…
#> # ℹ 7,936 more rows

age_example_edits <- age_example |>
  dplyr::mutate(age = years_floor(dob, dos)) |>
  dplyr::left_join(edits,
                   by = dplyr::join_by(icd_code),
                   relationship = "many-to-many") |>
  dplyr::filter(icd_conflict == "Age") |>
  apply_age_edits() |> 
  dplyr::select(
    dob,
    dos,
    age,
    icd_code,
    # icd_description,
    icd_limitation,
    conflict
  )

age_example_edits
#> # A tibble: 224 × 6
#>    dob        dos          age icd_code icd_limitation        conflict
#>    <date>     <date>     <dbl> <chr>    <chr>                 <chr>   
#>  1 2015-11-27 2023-01-08     7 Z00.00   Adult (Ages 15-124)   Conflict
#>  2 1990-11-07 2023-11-13    33 F53.0    Maternity (Ages 9-64) <NA>    
#>  3 2006-12-23 2023-09-26    16 F64.2    Pediatric (Ages 0-17) <NA>    
#>  4 1986-01-25 2023-08-05    37 Z91.82   Adult (Ages 15-124)   <NA>    
#>  5 1992-10-23 2023-06-29    30 O90.6    Maternity (Ages 9-64) <NA>    
#>  6 2014-01-25 2023-06-27     9 Z00.00   Adult (Ages 15-124)   Conflict
#>  7 2011-01-07 2023-04-12    12 F64.2    Pediatric (Ages 0-17) <NA>    
#>  8 1992-12-03 2023-03-02    30 F53.0    Maternity (Ages 9-64) <NA>    
#>  9 2000-11-12 2023-10-16    22 F53.0    Maternity (Ages 9-64) <NA>    
#> 10 1993-10-12 2022-12-13    29 F53.0    Maternity (Ages 9-64) <NA>    
#> # ℹ 214 more rows

age_example_edits |>
  dplyr::filter(!is.na(conflict))
#> # A tibble: 3 × 6
#>   dob        dos          age icd_code icd_limitation      conflict
#>   <date>     <date>     <dbl> <chr>    <chr>               <chr>   
#> 1 2015-11-27 2023-01-08     7 Z00.00   Adult (Ages 15-124) Conflict
#> 2 2014-01-25 2023-06-27     9 Z00.00   Adult (Ages 15-124) Conflict
#> 3 2012-05-11 2022-09-21    10 Z00.00   Adult (Ages 15-124) Conflict

pathologie::icd10cm("Z00.00") |> 
  dplyr::glimpse()
#> Rows: 1
#> Columns: 11
#> $ ch            <int> 21
#> $ abb           <chr> "STAT"
#> $ chapter_name  <chr> "Factors influencing health status and contact with heal…
#> $ chapter_range <chr> "Z00 - Z99"
#> $ section_name  <chr> "Encounter for general examination without complaint, su…
#> $ section_range <chr> "Z00 - Z00.8"
#> $ order         <int> 95509
#> $ valid         <int> 1
#> $ code          <chr> "Z00.00"
#> $ description   <chr> "Encounter for general adult medical examination without…
#> $ category      <chr> NA

Created on 2024-04-04 with reprex v2.1.0

@andrewallenbruce
Copy link
Owner Author

library(tidyverse)
library(pathologie)

years_floor <- function(from, to) {
  floor(as.double(difftime(to, from, units = "weeks", tz = "UTC")) / 52.17857)
}

apply_age_edits <- function(icd_conflict_rule, age) {

  msg <- "Age Conflict"

  dplyr::case_when(
    icd_conflict_rule == "Perinatal/Newborn (Age 0 Only)" & age != 0 ~ msg,
    icd_conflict_rule == "Pediatric (Ages 0-17)" & dplyr::between(age, 0, 17) == FALSE ~ msg,
    icd_conflict_rule == "Maternity (Ages 9-64)" & dplyr::between(age, 9, 64) == FALSE ~ msg,
    icd_conflict_rule == "Adult (Ages 15-124)" & dplyr::between(age, 15, 124) == FALSE ~ msg,
    .default = NA_character_
  )
}

exdata |>
  dplyr::mutate(patient_age = years_floor(date_of_birth, date_of_service)) |>
  dplyr::left_join(pathologie::search_edits(),
                   by = dplyr::join_by(icd_code), relationship = "many-to-many") |>
  dplyr::filter(!is.na(icd_description)) |>
  dplyr::arrange(date_of_service, icd_code) |>
  dplyr::mutate(conflict = apply_age_edits(icd_conflict_rule, patient_age)) |>
  dplyr::filter(!is.na(conflict)) |>
  dplyr::glimpse()

#> Rows: 11
#> Columns: 8
#> $ date_of_birth      <date> 2012-05-11, 2015-11-27, 2014-01-25, 2005-10-21, 20…
#> $ date_of_service    <date> 2022-09-21, 2023-01-08, 2023-06-27, 2023-10-26, 20…
#> $ icd_code           <chr> "Z00.00", "Z00.00", "Z00.00", "F64.2", "F64.2", "F6…
#> $ patient_age        <dbl> 10, 7, 9, 18, 18, 18, 18, 18, 18, 18, 18
#> $ icd_description    <chr> "Encntr for general adult medical exam w/o abnormal…
#> $ icd_conflict_group <chr> "Age", "Age", "Age", "Age", "Age", "Age", "Age", "A…
#> $ icd_conflict_rule  <chr> "Adult (Ages 15-124)", "Adult (Ages 15-124)", "Adul…
#> $ conflict           <chr> "Age Conflict", "Age Conflict", "Age Conflict", "Ag…

Created on 2024-04-05 with reprex v2.1.0

@andrewallenbruce andrewallenbruce changed the title Patient age validation ICD conflict rules Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant