我的R工作流程通常是打开一个文件,然后在其中输入R命令,并希望在一个单独打开的R shell中执行这些命令。
最简单的方法是在R中输入source('the-file.r')
。然而,这将重新加载整个文件,如果处理大量数据,则可能需要相当长的时间。同时,它还要求我再次指定文件名。
理想情况下,我希望只从文件中源引入特定的行(或多行)(我正在使用不支持复制和粘贴的终端)。
source
似乎没有提供此功能。是否有其他方法可以实现这一点?
我的R工作流程通常是打开一个文件,然后在其中输入R命令,并希望在一个单独打开的R shell中执行这些命令。
最简单的方法是在R中输入source('the-file.r')
。然而,这将重新加载整个文件,如果处理大量数据,则可能需要相当长的时间。同时,它还要求我再次指定文件名。
理想情况下,我希望只从文件中源引入特定的行(或多行)(我正在使用不支持复制和粘贴的终端)。
source
似乎没有提供此功能。是否有其他方法可以实现这一点?
这里是另一种仅使用R的方法:
source2 <- function(file, start, end, ...) {
file.lines <- scan(file, what=character(), skip=start-1, nlines=end-start+1, sep='\n')
file.lines.collapsed <- paste(file.lines, collapse='\n')
source(textConnection(file.lines.collapsed), ...)
}
正如评论中所讨论的,真正的解决方法是使用IDE,允许对文件的特定部分进行源代码编辑。有许多现成的解决方案:
对于Vim,有Nvim-R。
对于Emacs,有ESS。
当然还有优秀的独立RStudio IDE。
需要特别注意的是,以上所有解决方案都可在本地和服务器上(通过SSH连接等方式)工作。如果正确设置,R甚至可以在HPC集群上运行,仍可与IDE进行通信。
如果由于任何原因以上解决方案均无法使用,这里有一个小型模块[gist]可以完成任务。尽管如此,我通常不建议使用它。1
#' (Re-)source parts of a file
#'
#' \code{rs} loads, parses and executes parts of a file as if entered into the R
#' console directly (but without implicit echoing).
#'
#' @param filename character string of the filename to read from. If missing,
#' use the last-read filename.
#' @param from first line to parse.
#' @param to last line to parse.
#' @return the value of the last evaluated expression in the source file.
#'
#' @details If both \code{from} and \code{to} are missing, the default is to
#' read the whole file.
rs = local({
last_file = NULL
function (filename, from, to = if (missing(from)) -1 else from) {
if (missing(filename)) filename = last_file
stopifnot(! is.null(filename))
stopifnot(is.character(filename))
force(to)
if (missing(from)) from = 1
source_lines = scan(filename, what = character(), sep = '\n',
skip = from - 1, n = to - from + 1,
encoding = 'UTF-8', quiet = TRUE)
result = withVisible(eval.parent(parse(text = source_lines)))
last_file <<- filename # Only save filename once successfully sourced.
if (result$visible) result$value else invisible(result$value)
}
})
使用示例:
# Source the whole file:
rs('some_file.r')
# Re-soure everything (same file):
rs()
# Re-source just the fifth line:
rs(from = 5)
# Re-source lines 5–10
rs(from = 5, to = 10)
# Re-source everything up until line 7:
rs(to = 7)
1 有趣的故事:最近我发现自己在一个配置混乱的集群上,无法安装所需软件,但由于严峻的截止日期需要调试 R 工作流程。我只能手动复制和粘贴 R 代码行到控制台中。这是一个可能会派上用场的情况。是的,这真的发生了。
<<-
存储上一个源文件不是一个好主意(实际上,几乎从来不是一个好主意)。另一个问题是 sed
在所有平台上可能都不可用(例如 Windows)。 - Gabor Csardi.GlobalEnv
中确实是正确的方法。 - Gabor Csardised
,可以使用 readLines()
读取文件,然后选择所需的行并对其进行求值。 - Gabor Csardimissing
。 - mbq.GlobalEnv
中更好,如果变量名以点开头,则很好,因为它不会列在ls()
中,也不会在rm(list=ls())
中被删除等等。 - Gabor Csardi