R/fars_functions.R

#'  FARS data reading in CSV format
#'
#'  \code{fars_read} is a simple wrapper function for reading Comma-seperated
#'  Value (CSV) files with basic file handling and limited user interaction.
#'
#' @param filename A character object which corresponds to a valid path of the
#'  data file.
#' @details \code{fars_read} is a helper function for \code{fars_summarize_years}
#'  and \code{fars_read}.
#'
#'  In case the file does not exist an error message is produced and execution stops.
#' @return A object of the tbl_df class filled with data from specified file.
#' @importFrom readr read_csv
#' @importFrom dplyr tbl_df
#' @examples
#'  \donttest{
#'  library(farspkg)
#'  fh<-fars_read("accident_2013.csv.bz2")
#'  }
#' @export
fars_read <- function(filename) {
        if(!file.exists(filename))
                stop("file '", filename, "' does not exist")
        data <- suppressMessages({
                readr::read_csv(filename, progress = FALSE)
        })
        dplyr::tbl_df(data)
}

#'  FARS filename producing with requested year(s)
#'
#'  \code{make_filename} is a simple helper function which maps a specified
#'  year to its corresponding filename in the package structure.
#'
#' @param year An integer representing the requested datafile which belongs to
#'  the year from the package.
#' @return A string representing filename which contains data for the specified
#'  year.
#'
#'  In case the input can not be coerced to an integer, the string
#'  "accident_NA.csv.bz2" returned.
#' @details
#' This function is not designed for direct user interaction.
#'
#' \code{make_filename} is a helper function for \code{fars_read_years} and
#'
#' \code{fars_map_state}. There are no error handling.
#'
#' If a NULL object entered character(0) is returned.
#' @examples
#' \donttest{
#'  library(farspkg)
#'  make_filename("2015")
#'  make_filename(2014)
#'  }
make_filename <- function(year) {
        year <- as.integer(year)
        sprintf("accident_%d.csv.bz2", year)
}

#'  Cleaning FARS data for for summarizing(s)
#'
#'  \code{fars_read_years} is a simple helper function which reads FARS files
#'   with specified year and clean record structure to be reported with
#'   \code{fars_summarize_years}.
#'
#' @param years An integer/a list of integers to represent data files which
#'  needs to be read.
#' @return An object of the tbl_df class which includes only incident dates in
#'  Months and Years, per requested year.
#' @details
#' This function is not designed for direct user interaction.
#'
#' It is a helper function for \code{fars_summarize_years}.
#'
#' If any of the objects requested via input is not available as a year file
#'  or is not coercible to integer an "invalid year" error message returns.
#' @importFrom dplyr mutate select %>%
#' @examples
#' \donttest{
#'  library(farspkg)
#'  fars_read_years("2015")
#'  fars_read_years(c(2013.0,2014))
#'  }
fars_read_years <- function(years) {
        lapply(years, function(year) {
                file <- make_filename(year)
                tryCatch({
                        dat <- fars_read(file)
                        dplyr::mutate(dat, year = year) %>%
                                dplyr::select(MONTH, year)
                }, error = function(e) {
                        warning("invalid year: ", year)
                        return(NULL)
                })
        })
}

#' Summarizing FARS data for specific year(s).
#'
#' \code{fars_summarize_years} creates a summary table with counts of number of
#'  records for each month in a specified years.
#'
#' @param years An integer/a list of integers to query one or more years from
#'  the collection of datafiles.
#' @return An object of the tbl_df class which includes the month of a year in
#'  integer form as the first column and years in the requested order for
#'  following columns.
#'
#'  If any of the objects requested via input is not available as a year file or
#'  is not coercible to integer an "invalid year" error message returns.
#'
#' @importFrom dplyr bind_rows group_by summarize %>% n
#' @importFrom tidyr spread
#' @examples
#' \donttest{
#'  library(farspkg)
#'  fars_summarize_years("2015")
#'  fars_summarize_years(c(2013.0,2014))
#'  }
#' @export
fars_summarize_years <- function(years) {
  dat_list <- fars_read_years(years)
  dplyr::bind_rows(dat_list) %>%
    dplyr::group_by_("year", "MONTH") %>%
    dplyr::summarize_(n = ~n()) %>%
    tidyr::spread_("year", "n")
}

#' Drawing Maps with falatilies by state and year
#'
#' \code{fars_map_state} is function for plotting a map of the count of
#'  accidents in a specific state in a specific year.
#'
#' @details
#' \code{fars_map_state} function assumes that there will be a single integer
#'  value for state.num and single integer value for year. The implementation
#'  do not specifically check for these constraints.
#'
#'  If state does not exist in queried year: a error message of "nothing to draw:
#'   all regions out of bounds" apprears.
#'
#'  If multiple states will be entered as a vector: a warning message will appear
#'   stating "only the first element will be used", on the other hand, the graph
#'   will be created properly including all states inputted.
#'
#'  If an empty vector of states is inputted: an error message of "argument is of
#'   length zero" wil be displayed
#'
#'  If a non-existing year is entered: an error message of "Error in
#'   fars_read(filename) :" will be displayed.
#'
#'  If multiple years will be entered as a vector: an error message of
#'   "EXPR must be a length 1 vector" will be displayed.
#'
#'  If an empty vector of years is inputted: an error message of "argument is
#'   of length zero" wil be displayed
#'
#' @param state.num An integer representing a state as the index (between
#'  1 and 56).
#' @param year  An integer representing the year.
#' @importFrom graphics points
#' @importFrom maps map
#' @importFrom dplyr filter
#' @return This function returns a NULL object. But as a side effect a map
#'  where dots represent accidents also appears in a seperate window.
#' @examples
#' \donttest{
#'  library(farspkg)
#'  fars_map_state(1,2013)
#'  fars_map_state("1",2013.0)
#'  }
#' @export
fars_map_state <- function(state.num, year) {
        filename <- make_filename(year)
        data <- fars_read(filename)
        state.num <- as.integer(state.num)

        if(!(state.num %in% unique(data$STATE)))
                stop("invalid STATE number: ", state.num)
        data.sub <- dplyr::filter(data, STATE == state.num)
        if(nrow(data.sub) == 0L) {
                message("no accidents to plot")
                return(invisible(NULL))
        }
        is.na(data.sub$LONGITUD) <- data.sub$LONGITUD > 900
        is.na(data.sub$LATITUDE) <- data.sub$LATITUDE > 90
        with(data.sub, {
                maps::map("state", ylim = range(LATITUDE, na.rm = TRUE),
                          xlim = range(LONGITUD, na.rm = TRUE))
                graphics::points(LONGITUD, LATITUDE, pch = 46)
        })
}
umutkahramankaptan/farspkg documentation built on May 8, 2019, 1:24 p.m.