【问题标题】:How to modify pre-existing function in local environment in R如何在R中修改本地环境中的预先存在的功能
【发布时间】:2021-01-22 16:28:00
【问题描述】:

我正在尝试通过将现有函数复制并粘贴到 R 脚本并将其分配给本地环境中的新函数对象来修改现有函数。但是,新函数找不到在原始函数中调用的函数。如何在不单独查找和查找每个功能的情况下解决此问题?我猜测原始函数以某种方式链接到包或其依赖项,并且“知道在哪里寻找”丢失的函数,但我无法弄清楚如何使用我的新复制和粘贴函数来做到这一点。

library("camtrapR")

打印函数名

activityDensity

这里的输出是这个函数的代码。我在这里省略了它,因为它很长(并且我已将其粘贴在下面),但我完全复制并粘贴了函数代码的输出(请参阅下面我将这个确切代码分配给新函数的位置),除了最后两个输出行,我认为这很重要:

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

所以现在我将上面输出中的复制和粘贴代码分配给带有New &lt;-的新函数

   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))
  }
}

然而,当我尝试运行这个新函数时(为了清楚起见,这里省略了参数),它找不到嵌入其中的函数。

我怎样才能以某种方式分配此函数以在原始包camtrapR 中查找任何依赖项等?为什么函数的代码输出还没有这样做?

New()

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

这里的答案:https://stackoverflow.com/a/49277036/9096420 允许手动编辑和保存每个 R 会话的函数代码,但它是不可复制的(不是代码),可以共享或重复使用。

【问题讨论】:

  • 在定义环境后分配环境,即environment(New) &lt;- environment(oldFn),或者在每个内部函数前面加上package:::,或者将其全部放入一个新包中
  • 我知道它会很简单 - 只是我找不到的那些东西之一!谢谢你。是的,我想我可以为每个函数使用package::,但不想搜索它们都来自哪里。
  • 您在寻找hijack 函数吗?我发现这个 - trinkerrstuff.wordpress.com/2014/08/19/… - 在过去很有用。

标签: r function package


【解决方案1】:

如果 New 是从 camtrapR 复制的新函数,则使用

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

确保在其主体中的函数调用在正确的位置查找。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 2012-02-05
    • 2022-08-18
    • 1970-01-01
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多