R:我如何在包中添加额外的功能?

Posted

技术标签:

【中文标题】R:我如何在包中添加额外的功能?【英文标题】:R: How do I add an extra function to a package? 【发布时间】:2017-03-10 18:25:31 【问题描述】:

我想将一个特殊修改的函数添加到其他人编写的带有 R 脚本的包中,即仅用于会话,而不是永久。具体的例子是,比方说,bls_map_county2() 添加到 blscrapeR 包中。 bls_map_county2 只是 bls_map_county() 函数的副本,添加了 ... 参数,用于更改一些地图绘制参数。我还没有插入附加参数。按原样运行函数,我收到错误:

BLS_map_county 中的错误(map_data = df,fill_rate = "unused_rate",: 找不到函数“geom_map”

我认为这是因为我的函数没有指向 blscrapeR 命名空间。如何将我的函数分配给(已安装、已加载)blscrapeR 命名空间,我还需要做些什么来让它访问它需要的包中的任何机器吗?

【问题讨论】:

【参考方案1】:

这个答案有两个部分 - 首先是对您的问题的通用答案,第二部分是针对您引用的特定函数的具体答案,其中问题略有不同。

1) 编辑包函数时访问内部函数的通用解决方案

你应该已经可以访问包命名空间,因为你加载了它,所以只有未导出的函数会给你带来问题。

我通常只是将带有::: 运算符的包名称添加到非导出函数中。即,找到调用some_internal_function() 的每个实例,并将其替换为PackageName:::some_internal_function()。如果在您正在编辑的函数中调用了多个不同的内部函数,您可能需要为每个有问题的函数调用执行几次。

::: 的帮助页面确实包含这些警告

当心 - 使用 ':::' 风险自负!

在您的代码中使用 ::: 通常是一个设计错误,因为 相应的对象可能已长期保存在内部 原因。如果您觉得 需要访问该对象以进行任何检查。

但是对于您正在做的事情,就暂时从同一个包中破解另一个功能以供您自己使用而言,这些警告应该可以安全地忽略(当然,风险自负 - 正如手册中所说)

2) 在blscrapeR ::bls_map_county()的情况下

本例中的违规行是

ggplot2::ggplot() + geom_map(...

其中包编写者已为 ggplot() 指定 ggplot2 命名空间,但忘记为 geom_map() 这样做,这也是 ggplot2 的一部分(并且 不是 blscrapeR 中的内部函数)。

在这种情况下,只需加载 ggplot2,就可以了。

你也可以考虑联系包维护者,告知他们这个错误。

【讨论】:

谢谢@dww!因此,您将逐个功能地执行此操作。我在想你只是将 bls_map_county2 的父环境分配给 blascrapapeR 命名空间。 (如果那是我真正的问题,我的意思是)。但我不知道它叫什么。它不是命名空间:blscrapeR - R 对此做出回应,说它找不到名为命名空间的对象。【参考方案2】:

当我对特定包中的函数进行黑客攻击时,该函数又调用其他函数时,我经常在定义后使用这种形式:

mod_func <- function( args) body hacked
environment(mod_func) <- environment(old_func)

但我认为您可能真正想要的功能是assignInNamespace。这些方法将允许访问已加载包中的非导出函数。但是,如果未加载包,它们将不会成功。因此,您可能希望在 require(pkgname) 周围进行 stopifnot() 检查。

【讨论】:

谢谢@42!这非常有帮助。 ?有错字吗? mof_func 而不是 mod_func?请更正...

以上是关于R:我如何在包中添加额外的功能?的主要内容,如果未能解决你的问题,请参考以下文章

如何在包中只导入没有 exec __init__.py 的子模块

如何将示例项目添加到 Flutter 包中?

我如何在包中读取函数和过程 body/ddl?

如何在包中传递 View 的对象列表

如何使用静态库传输资源文件(如何将资源包装在包中)?

如何通过 GCM.send 在包中发送整数、布尔值