如何在调用其中的函数时获取R脚本文件名?

时间:2012-02-14 06:32:07

标签: r function filenames plyr

我有几个R脚本文件,例如f1.Rf2.Rf3.R

我有另一个名为AddSignal(signal)的函数,它将一个信号向量添加到列表中。 f1.R,f2.R等中的函数可以调用此AddSignal()函数。

现在我想要的是,在函数AddSignal()中,除了执行add信号部分之外,它还记录了R文件调用哪个函数。例如,我想知道f1.R中的函数ff1()添加了信号sig1。

有办法吗?

实际上,使用sys.call(),我可以知道哪个函数(例如,ff1())称为AddSignal()。但我不知道ff1()所在的哪个R文件。我可以看到一种难以实现的方法,就是扫描所有.R文件,然后存储文件名和函数名的映射。但是我想看看是否有更简单的方法。

感谢。

2 个答案:

答案 0 :(得分:6)

我要做的是创建一个查找表,将函数映射到它所在的.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获得的函数名称来执行映射。

编辑:鉴于您对非功能代码的评论,此代码使用parse,它不会评估代码。它搜索解析的输出,并清除函数,不应评估任何代码或返回非函数的代码。我没有详尽地测试它,试一试。

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),]

答案 1 :(得分:0)

您可以将AddSignal(signal)修改为

AddSignal(signal, filename=NULL){
  ...
  ...
  return(list(signal=signal,filename=filename))}