How to modify pre-existing function in local environment in R

Viewed 187

I am trying to modify an existing function by copy and pasting it to an R script, and assigning it to a new function object in my local environment. However the new function cannot find functions that are called to within the original function. How can I fix this without looking up and finding each function individually? I am guessing that the original function is somehow linked to the package or its dependencies and 'knows where to look' for the missing function, but I cannot figure out how to do this with my new copy-and-pasted function.

library("camtrapR")

Print the function name

activityDensity

The output here is the code for this function. I have omitted it here because it is long (and I have pasted it below), but I copy and paste the output of the function code exactly (see below where I assign this exact code to a new function), except for the last two lines of output, which I think are important:

<bytecode: 0x000000002a2d1e20>
<environment: namespace:camtrapR>

So now I assign the copy and pasted code from the output above to a new function with New <-

   New <- function (recordTable, species, allSpecies = FALSE, speciesCol = "Species", 
          recordDateTimeCol = "DateTimeOriginal", recordDateTimeFormat = "%Y-%m-%d %H:%M:%S", 
          plotR = TRUE, writePNG = FALSE, plotDirectory, createDir = FALSE, 
          pngMaxPix = 1000, add.rug = TRUE, ...) 
{
  wd0 <- getwd()
  mar0 <- par()$mar
  on.exit(setwd(wd0))
  on.exit(par(mar = mar0), add = TRUE)
  recordTable <- dataFrameTibbleCheck(df = recordTable)
  timeZone <- "UTC"
  checkForSpacesInColumnNames(speciesCol = speciesCol, recordDateTimeCol = recordDateTimeCol)
  if (!is.data.frame(recordTable)) 
    stop("recordTable must be a data frame", call. = FALSE)
  if (!speciesCol %in% colnames(recordTable)) 
    stop(paste("speciesCol = \"", speciesCol, "\" is not a column name in recordTable", 
               sep = ""), call. = FALSE)
  if (!recordDateTimeCol %in% colnames(recordTable)) 
    stop(paste("recordDateTimeCol = \"", recordDateTimeCol, 
               "\" is not a column name in recordTable", sep = ""), 
         call. = FALSE)
  stopifnot(is.logical(c(allSpecies, writePNG, plotR, createDir)))
  if (allSpecies == FALSE) {
    stopifnot(species %in% recordTable[, speciesCol])
    stopifnot(hasArg(species))
  }
  recordTable$DateTime2 <- parseDateTimeObject(inputColumn = recordTable[, 
                                                                         recordDateTimeCol], dateTimeFormat = recordDateTimeFormat, 
                                               timeZone = timeZone)
  recordTable$Time2 <- format(recordTable$DateTime2, format = "%H:%M:%S", 
                              usetz = FALSE)
  recordTable$Time.rad <- (as.numeric(as.POSIXct(strptime(recordTable$Time2, 
                                                          format = "%H:%M:%S", tz = timeZone))) - as.numeric(as.POSIXct(strptime("0", 
                                                                                                                                 format = "%S", tz = timeZone))))/3600 * (pi/12)
  if (isTRUE(writePNG)) {
    if (hasArg(plotDirectory)) {
      if (isTRUE(createDir)) {
        dir.create(plotDirectory, recursive = TRUE, showWarnings = FALSE)
        setwd(plotDirectory)
      }
      else {
        stopifnot(file.exists(plotDirectory))
        setwd(plotDirectory)
      }
    }
    else {
      stop("writePNG is TRUE. Please set plotDirectory", 
           call. = FALSE)
    }
  }
  pngWidth <- pngMaxPix
  pngHeight <- round(pngMaxPix * 0.8)
  if (allSpecies == FALSE) {
    subset_species <- subset(recordTable, recordTable[, speciesCol] == 
                               species)
    if (nrow(subset_species) == 1) 
      stop(paste(species, "had only 1 record. Cannot estimate density."), 
           call. = FALSE)
    try_error_tmp <- try({
      if (isTRUE(writePNG)) 
        png(filename = paste("activity_density_", 
                             species, "_", Sys.Date(), ".png", 
                             sep = ""), width = pngWidth, height = pngHeight, 
            units = "px", res = 96, type = "cairo")
      if (isTRUE(writePNG) | isTRUE(plotR)) {
        densityPlot(subset_species$Time.rad, main = paste("Activity of", 
                                                          species), rug = add.rug, ...)
        mtext(paste("number of records:", nrow(subset_species)), 
              side = 3, line = 0)
      }
      if (isTRUE(writePNG)) 
        dev.off()
    }, silent = TRUE)
    if (class(try_error_tmp) == "try-error") 
      warning(paste(toupper(species), ": ", try_error_tmp[1], 
                    "    - SKIPPED", sep = ""), call. = FALSE)
  }
  else {
    subset_species_list <- list()
    for (i in 1:length(unique(recordTable[, speciesCol]))) {
      spec.tmp <- unique(recordTable[, speciesCol])[i]
      subset_species <- subset(recordTable, recordTable[, 
                                                        speciesCol] == spec.tmp)
      plot_main_title <- paste("Activity of", spec.tmp)
      if (nrow(subset_species) == 1) {
        warning(paste(toupper(spec.tmp), ": It had only 1 record. Cannot estimate density.   - SKIPPED", 
                      sep = ""), call. = FALSE)
        next
      }
      else {
        try_error_tmp <- try({
          if (isTRUE(writePNG)) 
            png(filename = paste("activity_density_", 
                                 spec.tmp, "_", Sys.Date(), ".png", 
                                 sep = ""), width = pngWidth, height = pngHeight, 
                units = "px", res = 96, type = "cairo")
          if (isTRUE(writePNG) | isTRUE(plotR)) {
            densityPlot(subset_species$Time.rad, main = plot_main_title, 
                        rug = add.rug, ...)
            mtext(paste("number of records:", nrow(subset_species)), 
                  side = 3, line = 0)
          }
          if (isTRUE(writePNG)) 
            dev.off()
        }, silent = TRUE)
        if (class(try_error_tmp) == "try-error") 
          warning(paste(toupper(spec.tmp), ": ", 
                        try_error_tmp[1], "    - SKIPPED", 
                        sep = ""), call. = FALSE)
      }
      subset_species_list[[i]] <- subset_species$Time.rad
      names(subset_species_list)[i] <- spec.tmp
    }
  }
  if (allSpecies == FALSE) {
    return(invisible(subset_species$Time.rad))
  }
  else {
    return(invisible(subset_species_list))
  }
}

Yet, when I try to run this new function (arguments omitted here for clarity), it can't find a function embedded within.

How can I somehow assign this function to look within the original package camtrapR for any dependencies, etc.? and why does the code output from the function not already do this?

New()

Error in dataFrameTibbleCheck(df = recordTable) : 
  could not find function "dataFrameTibbleCheck"

This answer here: https://stackoverflow.com/a/49277036/9096420 allows one to manually edit and save a function's code for each R session, but it is non-reproducible (not code) that can be shared or re-used.

1 Answers

If New is the new function copied from camtrapR then use

environment(New) <- asNamespace("camtrapR")

to ensure that the function calls in its body are looked up in the correct places.

Related