Ответ 1
Во-первых, благодаря @Mathematical.coffee, чтобы поставить меня на путь использования пакета Mark Bravington mvbutils
. Функция foodweb
более чем удовлетворительна.
Напомним, что я хотел узнать о проверке одного пакета, скажем myPackage
по сравнению с другим, скажем externalPackage
, и об проверке скриптов на externalPackage
. Я продемонстрирую, как делать каждый. В этом случае внешний пакет data.table
.
1: для myPackage
по сравнению с data.table
достаточно следующих команд:
library(mvbutils)
library(myPackage)
library(data.table)
ixWhere <- match(c("myPackage","data.table"), search())
foodweb(where = ixWhere, prune = ls("package:data.table"), descendents = FALSE)
Это дает отличный график, показывающий, какие функции зависят от функций в data.table
. Хотя граф включает зависимости в пределах data.table
, он не слишком обременителен: я могу легко увидеть, какая из моих функций зависит от data.table
и какие функции они используют, например as.data.table
, data.table
, :=
, key
и т.д. На этом этапе можно сказать, что проблема зависимости пакета решена, но foodweb
предлагает гораздо больше, поэтому давайте посмотрим на это. Классная часть - это матрица зависимостей.
depMat <- foodweb(where = ixWhere, prune = ls("package:data.table"), descendents = FALSE, plotting = FALSE)
ix_sel <- grep("^myPackage.",rownames(depMat))
depMat <- depMat[ix_sel,]
depMat <- depMat[,-ix_sel]
ix_drop <- which(colSums(depMat) == 0)
depMat <- depMat[,-ix_drop]
ix_drop <- which(rowSums(depMat) == 0)
depMat <- depMat[-ix_drop,]
Это классно: теперь он показывает зависимости функций в моем пакете, где я использую подробные имена, например. myPackage.cleanData
, о функциях, не
в моем пакете, а именно функции в data.table
, и он исключает строки и столбцы, где нет зависимостей. Это краток, позволяет быстро просматривать зависимости, и я могу легко найти дополнительный набор для своих функций, обработав rownames(depMat)
.
NB: plotting = FALSE
, похоже, не мешает созданию графического устройства, по крайней мере, в первый раз, когда foodweb
вызывается в последовательности вызовов. Это раздражает, но не страшно. Возможно, я делаю что-то неправильно.
2: для скриптов по сравнению с data.table
это становится немного интереснее. Для каждого script мне нужно создать временную функцию, а затем проверить зависимости. У меня есть небольшая функция ниже, которая делает именно это.
listFiles <- dir(pattern = "myScript*.r")
checkScriptDependencies <- function(fname){
require(mvbutils)
rawCode <- readLines(fname)
toParse <- paste("localFunc <- function(){", paste(rawCode, sep = "\n", collapse = "\n"), "}", sep = "\n", collapse = "")
newFunc <- eval(parse(text = toParse))
ix <- match("data.table",search())
vecPrune <- c("localFunc", ls("package:data.table"))
tmpRes <- foodweb(where = c(environment(),ix), prune = vecPrune, plotting = FALSE)
tmpMat <- tmpRes$funmat
tmpVec <- tmpMat["localFunc",]
return(tmpVec)
}
listDeps <- list()
for(selFile in listFiles){
listDeps[[selFile]] <- checkScriptDependencies(selFile)
}
Теперь мне просто нужно взглянуть на listDeps
, и у меня есть такая же прекрасная маленькая информация, что и у depMat выше. Я изменил checkScriptDependencies
из другого кода, который написал, что отправляет скрипты, которые нужно проанализировать, codetools::checkUsage
; хорошо иметь такую небольшую функцию для анализа автономного кода. Kudos @Spacedman и @Tommy для понимания, который улучшил вызов foodweb
, используя environment()
.
(True hungaRians заметят, что я не согласен с порядком имени и типа - tooBad.:) Там больше причин для этого, но это не совсем тот код, который я использую.)
Хотя я не размещал изображения графиков, созданных foodweb
для моего кода, вы можете увидеть несколько приятных примеров на http://web.archive.org/web/20120413190726/http://www.sigmafield.org/2010/09/21/r-function-of-the-day-foodweb. В моем случае его вывод определенно захватывает использование data.table :=
и J
вместе со стандартными именованными функциями, такими как key
и as.data.table
. По-видимому, это устраняет мои текстовые поиски и улучшается несколькими способами (например, вы можете найти функции, которые я упустил).
В целом, foodweb
- отличный инструмент, и я рекомендую другим исследовать пакет mvbutils
и некоторые другие приятные пакеты Mark Bravington, такие как debug
. Если вы установите mvbutils
, просто проверьте ?changed.funs
, если считаете, что только вы боретесь с управлением эволюционирующим кодом R.:)