当加载两个包含同名函数的包时,会发生名称冲突。因此,可以在两个地方避免名称冲突:
创建具有唯一名称的函数
在撰写本文时(2017 年 8 月 23 日),CRAN 上提供了数量惊人的 11272 个软件包(最新数字可以在 here 找到),新软件包是 added every day。
因此,今天创建唯一的函数名称可能会在将来添加其他包时导致名称冲突。
Alistaire already has mentioned 为所有函数添加前缀的选项。除了stringi 和stringr,forcats 包是另一个使用前缀fct_ 和lvls_ 的例子。
这种方法可以大大降低名字冲突的可能性。
(虽然不能保证没有其他包维护者可以选择相同的前缀。)
使用双冒号运算符明确调用函数
恕我直言,避免名称冲突的最终责任在于用户。
我在这里看到了关于 SO 的问题,其中加载了六个以上的包。或者,为方便起见调用了library(tidyverse),它加载了其他19 个包,而dplyr 和tidyr 本来就足够了。
将命名空间与许多加载的包混淆会增加名称冲突的风险。即使只加载了两个包,也可能发生名称冲突。例如,lubridate 和 data.table 包都定义了
hour, isoweek, mday, minute, month, quarter, second, wday, week, yday, year
调用哪个函数取决于包的加载顺序。 (您可以使用conflicts() 在搜索路径上的两个或多个位置查找具有相同名称的对象。)
为避免歧义和意外结果,我建议加载尽可能少的包,并使用双冒号运算符?"::" 从包中调用函数,而无需预先加载包,例如,
library(data.table)
DT <- data.table(t = lubridate::now() + 0:3)
# call function from loaded package data.table
DT[, second(t)]
[1] 18 19 20 21
# call function from lubridate package
DT[, lubridate::second(t)]
[1] 18.88337 19.88337 20.88337 21.88337
使用双冒号运算符还有另一个好处。它将作为代码中的文档,从哪个包中调用函数。
这是以额外的几次击键为代价的,但在数周或数年后检查、修改或调试代码时可能会节省大量时间。我已经看到了很多关于 SO 的问题,其中 OP 没有提到包。