Read Oregon Medicaid Fee Schedules

Main website for OHP Data and Reports is here. The website for fee schedules is here.

  • Fee schedule are release quarterly
  • Oregon's Medicaid fee schedules come in either CSV, PDF, or Excel format; we'll download the CSV versions
  • File name format is in the form

      http://www.oregon.gov/oha/healthplan/DataReportsDocs/[monthname]%20YYYY%20Fee%20Schedule%20-%20CSV.csv

    monthname is generally Februrary, May, August, November; but is not consistent. Manual checking at the OHP fee schedules website is required.

  • report_date is not exact

    • It is parsed from the URL and uses the 1st of the month
    • It is not the actual date of the fee schedule report posted on the fee schedules website

In [1]:
library(data.table)
readFS <- function (url) {
    require(data.table, quietly=TRUE)
    require(lubridate, quietly=TRUE)
    x <- strsplit(url, "(%20)|/|-")[[1]]
    i <- grep("20[01][0-9]", x)
    year <- x[i]
    month <- x[i - 1]
    D <- fread(url, colClasses="character", na.strings=c(""))
    old <- names(D)
    new <- tolower(gsub("(\\s+)|(\\n)", "_", old))
    new <- gsub("^proc_code$", "procedure_code", new)
    new <- gsub("mod1|mod_1", "modifier_1", new)
    new <- gsub("mod2|mod_2", "modifier_2", new)
    setnames(D, old, new)
    D <- D[procedure_code != ""]
    D <- D[grep("^[0-9]+$", procedure_code), procedure_code := sprintf("%05d", as.integer(procedure_code))]
    D <- D[, price := as.numeric(gsub("(\\$)|(,)", "", price))]
    D <- D[, effective_date := fast_strptime(effective_date, "%Y%m%d")]
    D <- D[, report_date := as.Date(paste(month, "01", year), format="%B %d %Y")]
    if (!("modifier_2" %in% names(D))) {D <- D[, modifier_2 := NA_character_]}
    if (!("rate_type" %in% names(D))) {D <- D[, rate_type := NA_character_]}
    D[,
      .(procedure_code,
        description,
        modifier_1,
        modifier_2,
        rate_type,
        price,
        effective_date,
        report_date)]
}

In [2]:
urlStem <- "http://www.oregon.gov/oha/healthplan/DataReportsDocs/"
fs <- rbindlist(list(
    readFS(paste0(urlStem, "March%202010%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "May%202010%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "August%202010%20Fee%20Schedule%20-%20CSV.csv")),
    # readFS(paste0(urlStem, "December%202010%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "February%202011%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "May%202011%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "August%202011%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "November%202011%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "February%202012%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "May%202012%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "August%202012%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "November%202012%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "March%202013%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "August%202013%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "Nov%202013%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "February-March%202014%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "May-June%202014%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "August%202014%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "November%202014%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "February-March%202015%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "May%202015%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "August-September%202015%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "December%202015%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "February%202016%20Fee%20Schedule%20-%20CSV.csv")),
    readFS(paste0(urlStem, "April%202016%20Fee%20Schedule%20-%20CSV.csv"))
))
str(fs)


Attaching package: 'lubridate'

The following objects are masked from 'package:data.table':

    hour, mday, month, quarter, wday, week, yday, year

Classes 'data.table' and 'data.frame':	844662 obs. of  8 variables:
 $ procedure_code: chr  "00100" "00102" "00103" "00104" ...
 $ description   : chr  "ANESTH, SALIVARY GLAND" "ANESTH, REPAIR OF CLEFT LIP" "ANESTH, BLEPHAROPLASTY" "ANESTH, ELECTROSHOCK" ...
 $ modifier_1    : chr  NA NA NA NA ...
 $ modifier_2    : chr  NA NA NA NA ...
 $ rate_type     : chr  NA NA NA NA ...
 $ price         : num  24.2 24.2 24.2 24.2 24.2 ...
 $ effective_date: POSIXct, format: "2008-01-01" "2008-01-01" ...
 $ report_date   : Date, format: "2010-03-01" "2010-03-01" ...
 - attr(*, ".internal.selfref")=<externalptr> 

In [3]:
fs[, .N, report_date][order(report_date)]


Out[3]:
report_dateN
12010-03-0128080
22010-05-0128105
32010-08-0128104
42011-02-0126769
52011-05-0126812
62011-08-0126952
72011-11-0127005
82012-02-0127000
92012-05-0126988
102012-08-0126927
112012-11-0126920
122013-03-0126787
132013-08-0127130
142013-11-0127146
152014-03-0145997
162014-06-0145961
172014-08-0145973
182014-11-0146498
192015-03-0146171
202015-05-0146236
212015-09-0146732
222015-12-0146798
232016-02-0146903
242016-04-0146668

In [4]:
head(fs)
tail(fs)


Out[4]:
procedure_codedescriptionmodifier_1modifier_2rate_typepriceeffective_datereport_date
100100ANESTH, SALIVARY GLANDNANANA24.192008-01-012010-03-01
200102ANESTH, REPAIR OF CLEFT LIPNANANA24.192008-01-012010-03-01
300103ANESTH, BLEPHAROPLASTYNANANA24.192008-01-012010-03-01
400104ANESTH, ELECTROSHOCKNANANA24.192008-01-012010-03-01
500120ANESTH, EAR SURGERYNANANA24.192008-01-012010-03-01
600124ANESTH, EAR EXAMNANANA24.192008-01-012010-03-01
Out[4]:
procedure_codedescriptionmodifier_1modifier_2rate_typepriceeffective_datereport_date
1V5267Hearing aid sup/access/devNANANA72.922009-01-012016-04-01
2V5274Ald unspecifiedNANANA115.162009-01-012016-04-01
3V5336Repair communication deviceNANANA780.612009-01-012016-04-01
4V5362Speech screeningNANANA32.792009-01-012016-04-01
5V5363Language screeningNANANA32.792009-01-012016-04-01
6V5364Dysphagia screeningNANANA32.782009-01-012016-04-01

The December 2010 fee schedule throws an error. This can be fixed by using the dev version (1.9.7) of data.table, which adds a fill= argument to fread.


In [5]:
readFS(paste0(urlStem, "December%202010%20Fee%20Schedule%20-%20CSV.csv"))
readLines(paste0(urlStem, "December%202010%20Fee%20Schedule%20-%20CSV.csv"))[15169]


Error in fread(url, colClasses = "character", na.strings = c("")): Expecting 7 cols, but line 15169 contains text after processing all cols. It is very likely that this is due to one or more fields having embedded sep=',' and/or (unescaped) '\n' characters within unbalanced unescaped quotes. fread cannot handle such ambiguous cases and those lines may not have been read in as expected. Please read the section on quotes in ?fread.
Out[5]:
"59151,TREAT ECTOPIC PREGNANCY,AS,,,$111.67 ,20100101,,,,,,,"