% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/is_icd.R
\name{is_icd}
\alias{is_icd}
\title{Is ICD}
\usage{
is_icd(
  x,
  icdv = c(9L, 10L),
  dx = c(1L, 0L),
  src = c("cms", "who", "cdc"),
  year,
  headerok = FALSE,
  ever.assignable = missing(year),
  warn.ambiguous = TRUE,
  full.codes = TRUE,
  compact.codes = TRUE
)
}
\arguments{
\item{x}{Character vector of ICD codes (full or compact form).}

\item{icdv}{Integer vector of allowed ICD versions. Use \code{9L} and/or
\code{10L}. Defaults to both.}

\item{dx}{Integer vector indicating allowed code type(s): \code{1L} for
diagnostic (ICD-9-CM, ICD-10-CM, CDC mortality, WHO), \code{0L} for procedural
(ICD-9-PCS, ICD-10-PCS). Defaults to both.}

\item{src}{Character vector of code sources. One or more of \code{"cms"}, \code{"who"},
\code{"cdc"}. Defaults to all.}

\item{year}{Numeric scalar. Calendar or fiscal year to reference. Default
is the most current year available per source. For ICD-9, CMS data run
through fiscal year 2015 and CDC extracts through 2012; ICD-10 sources are
updated annually. Calendar year for WHO and CDC mortality. Fiscal year for
CMS.}

\item{headerok}{Logical scalar. If \code{FALSE} (default), only assignable
codes are considered valid; if \code{TRUE}, header codes are also accepted.}

\item{ever.assignable}{Logical scalar. If \code{TRUE} then ignore \code{year}
and return \code{TRUE} if the \code{x} was ever an assignable code.}

\item{warn.ambiguous}{Logical scalar. If \code{TRUE} (default), warn when a
code matches more than one ICD version and/or type (e.g., both CM and PCS).}

\item{full.codes}{Logical scalar. If \code{TRUE} (default), match codes that
include the decimal point where applicable.}

\item{compact.codes}{Logical scalar. If \code{TRUE} (default), match codes without
the decimal point.}
}
\value{
A logical vector the same length as \code{x}.
}
\description{
Answer the question "is the character string x a valid ICD code?"
ICD codes should be character vectors. \code{is_icd} will assess for both
"full codes" (decimal point present when appropriate) and "compact codes"
(decimal point omitted).

ICD-10 code "C00" is a header code because the four-character codes
C00.0, C00.1, C00.2, C00.3, C00.4, C00.5, C00.6, C00.7, C00.8, and C00.9
exist. Those four-character codes are assignable (as of 2025) because no
five-character descendants (e.g., C00.40) exist.

When the source is the World Health Organization (WHO) or CDC Mortality,
years refer to calendar years. CDC/CMS sources use the U.S. federal fiscal
year, which starts on October 1 (e.g., fiscal year 2024 runs 2023-10-01 to
2024-09-30).
}
\details{
Similarly for ICD-9-CM: "055" is a header for measles; 055.0, 055.1,
055.2, 055.8, and 055.9 are assignable. Codes 055.3–055.6 do not exist.
Code 055.7 is a header because 055.71 and 055.72 exist.

Some codes change status across years. For example, ICD-9-CM 516.3 was
assignable in fiscal years 1997–2011 for the CDC extracts (2006–2011 for CMS)
and became a header in 2012–2015.
}
\examples{
################################################################################
# Some ICD-9 diagnostic codes
x <- c("136.2", "718.60", "642.02")

is_icd(x, icdv =  9, dx = 1)
is_icd(x, icdv =  9, dx = 0)
is_icd(x, icdv = 10, dx = 1)
is_icd(x, icdv = 10, dx = 0)

is_icd(x, icdv = 9, dx = 1, headerok = TRUE)
is_icd(x, icdv = 9, dx = 1, year = 2006)

################################################################################
# ICD code with, or without a dot.  The ICD-9 diagnostic code 799.3 and ICD-9
# procedure code 79.93 both become 7993 when assessed against the ICD code look
# up tables.  As such "7993" is a valid ICD-9 diagnostic and procedure code,
# whereas 799.3 is only a valid dx code, and 79.93 is only a valid pr code.
# Further, codes such as ".7993", "7.993", "7993.", are all non-valid codes.

x <- c("7993", ".7993", "7.993", "79.93", "799.3", "7993.")
data.frame(
  x,
  dx = is_icd(x, icdv = 9, dx = 1),
  pr = is_icd(x, icdv = 9, dx = 0)
)

################################################################################
# example of a ICD-9 code that was assignable, but became a header when
# more descriptive codes were introduced: ICD-9 diagnostic code 516.3
lookup_icd_codes(paste0("516.3", c("", as.character(0:9))))

# ICD-9 code 516.3 was an assignable code through fiscal year 2011.
is_icd("516.3")

# If `year` is omitted, and `ever.assignable = FALSE` then the `year` is
# implied to be the max `known_end` year for ICD codes matched by `icdv`,
# `dx`, and `src`.
is_icd("516.3", ever.assignable = FALSE)

# when `year` is provided then `ever.assignable` is `FALSE` by default and
# the return is TRUE when 516.3 was assignable and FALSE otherwise.
is_icd("516.3", year = 2015)
is_icd("516.3", year = 2011)

# when year is a non-assignable year, but `ever.assignable = TRUE` the return
# will be TRUE.  Useful if you know the data is retrospective and collected
# through fiscal year 2015.
is_icd("516.3", year = 2015, ever.assignable = TRUE)

################################################################################
# Consiser the string E010
#   - This could be a ICD-9-CM full code
#   - Could be a ICD-10-CM compact code
lookup_icd_codes("E010")
subset(get_icd_codes(with.descriptions = TRUE), grepl("^E010$", code))

is_icd("E010")
is_icd("E010", icdv = 9) # FALSE because it is a header code and was never assignable
is_icd("E010", icdv = 9, ever.assignable = TRUE) # FALSE
is_icd("E010", icdv = 9, headerok = TRUE) # TRUE
}
\seealso{
\itemize{
\item \code{\link[=get_icd_codes]{get_icd_codes()}} to retrieve the internal lookup table of ICD codes.
\item \code{\link[=lookup_icd_codes]{lookup_icd_codes()}} for retrieving details on a specific set of ICD
codes.
\item \code{\link[=icd_compact_to_full]{icd_compact_to_full()}} converts a string from a compact format to the
full format based on ICD version and type (diagnostic or procedure).
}

Other ICD tools:
\code{\link[=icd_compact_to_full]{icd_compact_to_full()}},
\code{\link[=lookup_icd_codes]{lookup_icd_codes()}}
}
\concept{ICD tools}
