Skip to content

Commit

Permalink
Change multimaps() predicate ignore strategy
Browse files Browse the repository at this point in the history
Ignore unknown predicates. Handle missing predicates as
defined by new `when_pred_NA` argument.

Tests: PASS
  • Loading branch information
allenbaron committed Jan 26, 2024
1 parent fcf08db commit 150404e
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 53 deletions.
47 changes: 15 additions & 32 deletions R/inventory.R
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
#' @export
inventory_omim <- function(onto_path, omim_input, keep_mim = c("#", "%"),
include_pred = c("skos:exactMatch", "skos:closeMatch", "oboInOwl:hasDbXref"),
ignore_pred = c("skos:narrowMatch", "skos:broadMatch", "skos:relatedMatch")) {
when_pred_NA = "error") {
stopifnot("`onto_path` does not exist." = file.exists(onto_path))

if ("omim_tbl" %in% class(omim_input)) {
Expand Down Expand Up @@ -133,19 +133,21 @@ inventory_omim <- function(onto_path, omim_input, keep_mim = c("#", "%"),
#' "multiple" in the "one-to-multiple" test).
#' @param include_pred The predicates to include when testing for one-to-multiple
#' mappings, as a character vector (default: `skos:exactMatch`,
#' `skos:closeMatch`, and `oboInOwl:hasDbXref`).
#' @param ignore_pred The predicates to ignore when testing for one-to-multiple
#' mappings, as a character vector (default: `skos:narrowMatch`,
#' `skos:broadMatch`, and `skos:relatedMatch`). Any predicates not missing
#' or included in `test_pred` and `ignore_pred` will result in an error.
#' `skos:closeMatch`, and `oboInOwl:hasDbXref`). All other predicates are
#' ignored.
#' @param when_pred_NA What to do when missing predicates are detected, as a
#' string; one of "error" (default), "warn", or NULL (do nothing). `NA`
#' predicates are _always_ ignored when no mapping exists (i.e. one or both
#' corresponding values of `x` or `y` is/are also `NA`).
#'
#' @returns A logical vector specifying the positions in `x` that map to
#' multiple values in `y`.
#' multiple values in `y`. Incomplete mappings, where values of `x`, `y`, or
#' both are `NA`, are ignored and return `FALSE`.
#'
#' @keywords internal
multimaps <- function(x, pred, y,
include_pred = c("skos:exactMatch", "skos:closeMatch", "oboInOwl:hasDbXref"),
ignore_pred = c("skos:narrowMatch", "skos:broadMatch", "skos:relatedMatch")) {
when_pred_NA = "error") {
stopifnot(
"`x`, `pred`, & `y` must be the same length" =
dplyr::n_distinct(c(length(x), length(pred), length(y))) == 1
Expand All @@ -156,37 +158,18 @@ multimaps <- function(x, pred, y,
return(out)
}

include_pattern <- unique_to_string(include_pred, delim = "|", na.rm = FALSE)
ignore_pattern <- unique_to_string(ignore_pred, delim = "|", na.rm = FALSE)

p_incl <- stringr::str_detect(pred, include_pattern)
p_ignore <- stringr::str_detect(pred, ignore_pattern)
p_missing <- is.na(pred) & !is.na(x) & !is.na(y)
p_unknown <- !(p_incl | p_ignore | is.na(pred))

if (any(p_missing | p_unknown)) {
pred_err <- unique(pred[p_missing | p_unknown])
err_details <- purrr::map_chr(
pred_err,
function(.x) {
if (is.na(.x)) {
.loc <- which(p_missing)
} else {
.loc <- which(pred == .x)
}
paste0(.x, " [pos: ", to_range(.loc), "]")
}
)
names(err_details) <- rep("x", length(err_details))

if (any(p_missing)) {
rlang::abort(
c(
"All predicates must be included in `include_pred` or `ignore_pred`",
err_details
"Predicates must not be missing from mappings",
x = paste0("`pred` = `NA` [", to_range(which(p_missing)), "]")
)
)
}

include_pattern <- unique_to_string(include_pred, delim = "|")
p_incl <- stringr::str_detect(pred, include_pattern)
pi_split <- split(p_incl, x)
y_split <- split(y, x)
multimaps <- vapply(
Expand Down
13 changes: 7 additions & 6 deletions man/inventory_omim.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions man/multimaps.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 11 additions & 8 deletions tests/testthat/test-inventory.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,29 @@
6L, "c", "oboInOwl:hasDbXref|skos:exactMatch", "C"
)

test_that("multimap() works with default include & ignore predicates", {
test_that("multimap() works with defaults", {
expect_equal(multimaps(.tbl$x, .tbl$p, .tbl$y), c(T, T, F, F, T, T))
expect_equal(multimaps(.tbl$y, .tbl$p, .tbl$x), c(T, T, T, F, T, F))
})

test_that("multimaps() ignores unknown predicates", {
.tbl$p[2] <- "random:mapping"
expect_equal(multimaps(.tbl$x, .tbl$p, .tbl$y), c(F, F, F, F, T, T))
expect_equal(multimaps(.tbl$y, .tbl$p, .tbl$x), c(T, F, T, F, F, F))
})

test_that("multimap() works including only skos:(exact|close)Match, excludes oboInOwl:hasDbXref", {
expect_equal(
multimaps(
.tbl$x, .tbl$p, .tbl$y,
include_pred = c("skos:exactMatch", "skos:closeMatch"),
ignore_pred = c("skos:narrowMatch", "skos:broadMatch", "skos:relatedMatch", "oboInOwl:hasDbXref")
include_pred = c("skos:exactMatch", "skos:closeMatch")
),
c(T, T, F, F, F, F)
)
expect_equal(
multimaps(
.tbl$y, .tbl$p, .tbl$x,
include_pred = c("skos:exactMatch", "skos:closeMatch"),
ignore_pred = c("skos:narrowMatch", "skos:broadMatch", "skos:relatedMatch", "oboInOwl:hasDbXref")
include_pred = c("skos:exactMatch", "skos:closeMatch")
),
c(F, F, F, F, F, F)
)
Expand All @@ -40,11 +44,10 @@ test_that("multimaps() returns all `FALSE` when either input has only `NA`", {
expect_equal(multimaps(.tbl$x, .tbl$p, .tbl$y), rep(FALSE, 3))
})

test_that("multimaps() errors for unknown/missing predicates", {
.tbl$p[2] <- "random:mapping"
test_that("multimaps() errors for missing predicates", {
.tbl$p[c(1,3)] <- NA
expect_error(
multimaps(.tbl$x, .tbl$p, .tbl$y),
regexp = "NA.*1,3.*random:mapping.*2"
regexp = "`pred` = `NA` \\[1,3\\]"
)
})

0 comments on commit 150404e

Please sign in to comment.