我有一个非常长的R脚本,包含许多if语句和异常情况。正如我一直在进行的那样,如果我已经去过导入和测试库,并且没有真正记录它们。问题是如果我从一个干净的安装中运行它,我不确定脚本将运行哪些语句,以及需要哪些库。
我的问题是:是否有任何R函数来测试脚本中正在使用哪些库?
编辑:我没有使用已安装的所有库,因此print(sessionInfo())
不会有用,但我只想用{{1}启动脚本功能
答案 0 :(得分:4)
我不确定自动化的好方法......但你能做的是:
与sessionInfo
核实您没有加载额外的包裹。
您可以使用sessionInfo
进行检查。如果您默认加载额外的软件包(例如使用.RProfile文件),我建议您不要这样做,因为它是灾难的一种方法。
通常,您应该只加载基础包:stats
,graphics
,grDevices
,utils
,datasets
,methods
和{{1 }}
您可以使用以下方法卸载任何额外的库:
base
现在,在对所有detach("package:<packageName>", unload=TRUE)
和library
来电进行评论后运行该脚本,并查看哪些函数出错。
要获取控制台中每种功能类型所需的软件包:
require
加载所需的软件包并重新运行步骤3-5直到满意为止。
答案 1 :(得分:3)
我之前使用过a shell script:
#!/usr/bin/env bash
source_files=($(git ls-files '*.R'))
grep -hE '\b(require|library)\([\.a-zA-Z0-9]*\)' "${source_files[@]}" | \
sed '/^[[:space:]]*#/d' | \
sed -E 's/.*\(([\.a-zA-Z0-9]*)\).*/\1/' | \
sort -uf \
> DEPENDS
这使用Git收集项目中版本控制下的所有R文件。由于你应该使用版本控制这通常是一个很好的解决方案(尽管你可能想要调整版本控制系统)。对于项目不受版本控制的少数情况,您应该(1)将其置于版本控制之下。或者,如果不这样做,(2)使用find . -regex '.*\.[rR]'
代替git ls-files '*.R'
。
它产生一个DEPENDS
file,其中包含一个非常简单的依赖列表。
它只能找到对library
和require
的直接调用 - 如果你打包这些调用,脚本将无效。
答案 2 :(得分:3)
我发现NCmisc(list.functions.in.file()
)的install.packages("NCmisc")
函数对此很有帮助:
list.functions.in.file(filename, alphabetic = TRUE)
有关更多信息,请参见以下链接:https://rdrr.io/cran/NCmisc/man/list.functions.in.file.html
答案 3 :(得分:1)
您可能需要在GitHub上查看Revolution Analytics的检查点功能:https://github.com/RevolutionAnalytics/checkpoint
它做了一些,并解决了再现性问题。但我不认为它可以报告你正在使用的列表。
但是,如果您查看代码,您可能会得到一些想法。
答案 4 :(得分:1)
当我需要将代码转换为包时,我有类似的需求,因此我需要识别每个包依赖项并导入或使用完全限定名称。
在阅读书Extending R
中,我发现XRtools::makeImports
可以扫描包并找到需要导入的所有包。这并没有解决我们的问题,因为它只适用于现有的包,但它提供了如何做的主要见解。
我创建了一个函数并将其放入我的包mischelper
中。您可以安装软件包,使用RStudio addin菜单扫描当前文件或选定的代码,或使用命令行功能。每个外部函数(fun_inside)和调用它的函数(用法)都将列在表中。
您现在可以转到每个功能,按F1查找它所属的包。我实际上有另一个软件包可以扫描所有已安装的软件包以获取函数名称并构建数据库,但这可能会导致更多的误报,因为如果你只加载了一些软件包,按F1键只搜索已加载的软件包。
在我的包页面中查看用法的详细信息
答案 5 :(得分:0)
基于每个人的回应,尤其是eh21对NCmisc软件包的建议,我整理了一个小函数,该函数还输出目录中所有R脚本中使用的软件包列表。作为他们的频率。
library(NCmisc)
library(stringr)
library(dplyr)
checkPacks<-function(path){
## get all R files in your directory
## by the way, extract R code from Rmd: http://felixfan.github.io/extract-r-code/
files<-list.files(path)[str_detect(list.files(path), ".R$")]
## extract all functions and which package they are from
## using NCmisc::list.functions.in.file
funs<-unlist(lapply(paste0(path, "/", files), list.functions.in.file))
packs<-funs %>% names()
## "character" functions such as reactive objects in Shiny
characters<-packs[str_detect(packs, "^character")]
## user defined functions in the global environment
globals<-packs[str_detect(packs, "^.GlobalEnv")]
## functions that are in multiple packages' namespaces
multipackages<-packs[str_detect(packs, ", ")]
## get just the unique package names from multipackages
mpackages<-multipackages %>%
str_extract_all(., "[a-zA-Z0-9]+") %>%
unlist() %>%
unique()
mpackages<-mpackages[!mpackages %in% c("c", "package")]
## functions that are from single packages
packages<-packs[str_detect(packs, "package:") & !packs %in% multipackages] %>%
str_replace(., "[0-9]+$", "") %>%
str_replace(., "package:", "")
## unique packages
packages_u<-packages %>%
unique() %>%
union(., mpackages)
return(list(packs=packages_u, tb=table(packages)))
}
checkPacks("~/your/path")