Как получить имя файла R-скрипта, когда в нем вызывается функция? - PullRequest
3 голосов
/ 14 февраля 2012

У меня есть несколько файлов сценариев R, таких как f1.R, f2.R, f3.R.

У меня есть еще одна функция, называемая AddSignal (сигнал), которая добавляет вектор сигнала в список.Функции в f1.R, f2.R и т. Д. Могут вызывать эту функцию AddSignal ().

Теперь я хочу, чтобы в функции AddSignal () помимо части сигнала добавления она также записывалафункция, в которой R файл сделал вызов.Например, я хотел бы знать, что функция ff1 () в f1.R добавила сигнал sig1.

Есть ли способ сделать это?

На самом деле, используя sys.call ()Я могу знать, какая функция (например, ff1 ()) называется AddSignal ().Но я не знаю, в каком R-файле находится ff1 (). Я вижу сложный способ сделать это - отсканировать все .R-файлы и затем сохранить сопоставление имен файлов и имен функций.Но я хотел бы посмотреть, есть ли более простой способ сделать это.

Спасибо.

1 Ответ

6 голосов
/ 14 февраля 2012

Что я хотел бы сделать, это создать справочную таблицу, которая сопоставляет функцию с файлом .R, в котором она находится. Вам необходимо пересоздавать эту таблицу каждый раз, когда вы добавляете, удаляете или перемещаете функцию, но я думаю, что это будетпредпочтительнее регенерации таблицы каждый раз, когда вы хотите найти исходный файл функции.Итак, вот мой взгляд на создание такой таблицы:

library(plyr)

functionsFromRfile = function(filename) {
# Get all functions from a source file. Create new enviroment
# source the functions into them and use ls() to extract names.
  e = new.env()
  source(filename, local = e)
  return(ls(envir = e))
}

# This assumes you are in the directory with your R code,
# and that all files need to be included. You can also
# make this list manually ofcourse
Rfiles = list.files(".", pattern = ".R")
# Get a list of functions for each .R file
lutFunc2sourcefile = ldply(Rfiles, function(x) {
  return(data.frame(fname = x, func = functionsFromRfile(x)))
})

Для одного из моих собственных пакетов это приводит к:

> head(lutFunc2sourcefile)
               fname                func
1 autofitVariogram.r    autofitVariogram
2     autoKrige.cv.r        autoKrige.cv
3     autoKrige.cv.r checkIfautokrige.cv
4     autoKrige.cv.r          compare.cv
5     autoKrige.cv.r   cv.compare.bubble
6     autoKrige.cv.r   cv.compare.ggplot

Вы можете использовать таблицу поиска для выполнения отображения, используяимя функции, полученное из sys.call.

EDIT : С учетом вашего комментария к нефункциональному коду этот код использует синтаксический анализ, который не оценивает код.Он просматривает результаты анализа и отсеивает функции и не должен оценивать какой-либо код или код возврата, который не является функцией.Я не проверил это исчерпывающе, попробуй.

library(plyr)

Rfiles = list.files(".", pattern = "(.R|.r)")
lutFunc2sourcefile = ldply(Rfiles, function(fname) {
   f = parse(fname)
   functions = sapply(strsplit(as.character(f), "="), function(l) {
     if(grepl("^function", sub(' ', '', l[2]))) {
       return(l[1])
     } else {
       return(NA)
     }
    })
   return(data.frame(fname, func = functions))  
})
# Remove lines with func = NA
lutFunc2sourcefile = lutFunc2sourcefile[!is.na(lutFunc2sourcefile$func),]
...