修改R包函数以适应当前的R会话;assignInNamespace与fixInNamespace的行为不同?

16

我想以“自动化”的方式修改R包中的隐藏函数,就像使用fixInNamespace一样,但我想提前编写代码,而不是在“编辑”窗口中执行fixInNamespace。我认为assignInNamespace可以完成这项工作,但目前它无法正常工作。以下是问题的一个示例。

require(quantmod)

getSymbols("AAPL")

chartSeries(AAPL)  # Works fine up to here. 

现在假设我想把y轴刻度绘制在图的左侧而不是右侧。这可以通过修改quantmod软件包中的源代码来实现。修改绘图布局的相关代码位于一个隐藏的 quantmod函数中,名为chartSeries.chob

可以通过以下方式完成此操作:

fixInNamespace("chartSeries.chob", ns = "quantmod")
在编辑窗口中,将第117行手动修改为axis(2),单击“确定”,然后再次运行chartSeries(AAPL)(现在y轴标签将绘制在图的左侧)。一切都很好,生成了预期的图形,没有问题。
但是,现在假设我想提前修改chartSeries.chob(通过自动化方式),可能是通过引用修改版本的chartSeries.chob函数,而不使用编辑窗口。例如,我可能想要修改函数中的几十行,并且每个新的R会话都打开编辑窗口不太实际。
我该怎么办?
目前我正在尝试以下操作,但并没有起作用:
assignInNamespace("chartSeries.chob", value = chartSeries.chob2, ns = "quantmod")

我从控制台中获取了完整的chartSeries.chob副本,并且修改了第117行的代码。

chartSeries.chob2 <- function (x) 
{
old.par <- par(c("pty", "mar", "xpd", "bg", "xaxs", "las", 
                   "col.axis", "fg"))
  on.exit(par(old.par))
....

[Edit On 117:] axis(2)
...
}

当我在控制台中运行时:

chartSeries(AAPL)
或者
quantmod:::chartSeries(AAPL)

我遇到了错误 -- 在 chartSeries.chob 函数内部调用 quantmod 中的其他函数时无法找到它们,这可能是因为编辑后的 chartSeries.chob 函数不在 quantmod 命名空间中?

我注意到,在执行 assignInNamespace 命令后从控制台键入 quantmod:::chartSeries.chob 时,函数定义结尾处没有 environment: namespace:quantmod

但如果我采用 fixInNamespace 修改方法,当我键入 quantmod:::chartSeries.chob 时,我会看到 environment: namespace:quantmod 添加到函数定义的结尾处。

1个回答

21

由于fixInNamespace调用了assignInNamespace,所以你应该能够让它正常工作,问题可能是环境不同,可能还有其他一些属性。如果你将它们改为匹配,我会期望它能更好地工作,可能使用以下代码:

tmpfun <- get("chartSeries.chob", envir = asNamespace("quantmod"))
environment(chartSeries.chob2) <- environment(tmpfun)
attributes(chartSeries.chob2) <- attributes(tmpfun)  # don't know if this is really needed
assignInNamespace("chartSeries.chob", chartseries.chob2, ns="quantmod")

对于某些更改的另一个选项是使用trace函数。 这将进行临时更改,并且适用于插入代码,但我不知道是否合理删除命令或直接修改(指定更改代码的编辑器而不是让您更改它可能会使此变得可能)。


2
@FXQuantTrader,抱歉那是我打错了字,我已经改正了。应该用 envir 而不是 ns,并且你需要使用 asNamespace。我从 fixInNamespace 的代码中复制了错误的部分。 - Greg Snow
3
现在它可以运行了!太好了。秘密的关键是将envir设置为asNamespace("quantmod"),而不是像envir = as.environment("package:quantmod")这样的东西。有点混乱,但您的解决方案可行。谢谢!如果以后有人感兴趣的话,似乎不需要attributes(chartSeries.chob2) <- attributes(tmpfun)来使assignInNamespace正常工作。 - FXQuantTrader
2
我尝试使用fame包中的可见函数来完成这个任务,但每当我运行assignInNamespace("getfame", getfame2,ns = "fame")assignInNamespace("getfame", getfame2,ns = asNamespace("fame"))时,当我输入getfame时,仍旧会返回旧的包默认值。 - Matt Bannert
1
@Matt Bannert 请尝试在可见函数的函数调用前加上包命名空间,例如 fame:::getfame。然后它应该可以工作了;默认情况下,R仍将选择原始函数。如果我记得正确,我认为如果您卸载包、修复命名空间,然后重新加载包,您可能不需要在前面加上命名空间。 - FXQuantTrader
1
@FXQuantTrader 问题在于 getfame 是一种比较底层的函数,通常不会自己调用它。它是由另一个包作者的各种函数调用的(我已经和他交谈过,但需要等修复方案出现)。同时,即使我直接调用而没有使用 fame::,但是依赖的包仍然调用旧函数,即使它们在调用时没有使用 fame::。如果它们使用了 fame:: 就不必这样做,因为我的问题是由于遮蔽这些函数引起的。 - Matt Bannert
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接