简体   繁体   English

如何在R编程中将当前文件位置设置为默认工作目录?

[英]How to set the current file location as the default working directory in R programming?

I want to make the current file location as the working directory. 我想将当前文件位置作为工作目录。

Using Rstudio (Works!): 使用Rstudio(Works!):

# Author  : Bhishan Poudel
# Program : writehere.r
# Source  : Rscript writehere.r

# set working directory here
this.dir <- dirname(parent.frame(2)$ofile) # frame(3) also works.
setwd(this.dir)

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")
#This works flawlessly in  MacOS 10.9 and Ubuntu 15.1.

Using Command from terminal : Rscript writehere.r (Does not work!) 使用来自终端的命令:Rscript writehere.r(不起作用!)

Error in dirname(parent.frame(2)$ofile) : 
  a character vector argument expected
Execution halted


------------------
(program exited with code: 1)

Using Command from terminal : Rscript writehere.r (Works now!) 使用终端命令:Rscript writehere.r(立即工作!)

# Author  : Bhishan Poudel
# Program : writehere.r
# Source  : Rscript example.r

# set working directory here
this_dir <- function(directory)
setwd( file.path(getwd(), directory) )

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")

Using function inside ~/.Rprofile for Rstudio (Works!) : , 使用〜/ .Rprofile里面的函数为Rstudio(Works!):,

##############################################
# inside ~/.Rprofile
# set up working directory
setwd_thisdir <- function () {
  this.dir <- dirname(parent.frame(3)$ofile)
  setwd(this.dir)
} 
##############################################

Then, in any directory let's say I have a file writehere.r, now it works. 然后,在任何目录中,假设我有一个文件writehere.r,现在它可以工作。

# Author  : Bhishan Poudel
# Program : writehere.r
# Compile : Rscript writehere.r

# set working directory here
setwd_thisdir

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")

Question: Why the function 问题:为什么功能

this.dir <- dirname(parent.frame(2)$ofile) # frame(3) also works.
setwd(this.dir)

does not work for text editors other than Rstudio? 不适用于Rstudio以外的文本编辑器?

Some useful links are following: 一些有用的链接如下:
R setting working directory to source file location? R将工作目录设置为源文件位置?
R command for setting working directory to source file location R命令用于将工作目录设置为源文件位置
get filename and path of `source`d file 获取`source`d文件的文件名和路径
setwd() in the current working dir 当前工作目录中的setwd()
Command for "Set working directory to source file location" “将工作目录设置为源文件位置”的命令
SublimeText and R: Setting Current File Directory SublimeText和R:设置当前文件目录
Setting working directory through a function 通过函数设置工作目录
What is a fool-proof way of permanently setting R working directory? 什么是永久设置R工作目录的万无一失的方法?
R setting working directory to source file location? R将工作目录设置为源文件位置?
How to get into the directory of a file in R? 如何进入R中的文件目录?

Try using parent.frame(3) in you function: 尝试在函数中使用parent.frame(3)

setwd_thisdir <- function () {
  this.dir <- dirname(parent.frame(3)$ofile)
  setwd(this.dir)
}

See ?parent.frame or http://adv-r.had.co.nz/Environments.html#calling-environments . 请参阅?parent.framehttp://adv-r.had.co.nz/Environments.html#calling-environments

You may also look at the chdir option of the source function ( ?source ). 您还可以查看source函数的chdir选项( ?source )。

UPDATE: I realised that this answer didn't help at all, and I will post another one that does the trick. 更新:我意识到这个答案根本没有帮助,我会发布另一个可以解决问题的方法。

Insofar the code you want to run doesn't need any additional arguments, a solution as sketched below, using eval(expr, envir) might do the trick. 在你想要运行的代码不需要任何其他参数的情况下,如下所示的解决方案,使用eval(expr, envir)可能会有所帮助。

Consider the following example using print(environment()) , which should return environment: R_GlobalEnv when used on the command line. 请考虑以下使用print(environment())示例,该示例应在命令行上使用时返回environment: R_GlobalEnv The function test_1 will print information about the internal environment that is created when the function is called, whereas the function test_2 will return the desired result. 函数test_1将打印有关调用函数时创建的内部环境的信息,而函数test_2将返回所需的结果。

test_1 <- function(){
     print(environment())
}

test_2 <- function(){
    .expr <- quote({
        print(environment())
        })
    .envir <- sys.frame(which = -1)
    eval(expr = .expr,
         envir = .envir)
}

The sys.frame(which = -1) ensures that the expression is evaluated in the environment where the function is called. sys.frame(which = -1)确保在调用函数的环境中计算表达式。 If you are certain that you always want to use the global environment, then it's better to use .GlobalEnv . 如果您确定总是想要使用全局环境,那么最好使用.GlobalEnv It's also important to quote the expression you want to use, otherwise it might not work as desired. 引用您想要使用的表达式也很重要,否则它可能无法正常工作。

A nice feature of this solution is that you don't need to tweak the code you want to put into the function, just quote it. 这个解决方案的一个很好的功能是你不需要调整你想要放入函数的代码,只需引用它。

Finally: It's possible to extend this approach such that your function can take arguments that then will be given to the code you want to evaluate in another environment. 最后:可以扩展这种方法,以便您的函数可以接受参数,然后将该参数提供给您想要在另一个环境中评估的代码。 This will however require a bit of non-trivial tweaking upon the expression you want to evaluate; 然而,这需要对要评估的表达式进行一些非平凡的调整; you might need to use the bquote + .() construction - and you might in addition also need to use call and do.call . 你可能需要使用bquote + .()构造 - 你可能还需要使用calldo.call

The first answer I gave missed the point completely, since I hadn't looked closely upon what you wanted to achieve. 我给出的第一个答案完全忽略了这一点,因为我没有密切关注你想要实现的目标。 The solution presented here should however do the trick. 然而,这里提出的解决方案应该是诀窍。

First note that source has an argument chdir that in the help-file is described with: logical; 首先请注意, source有一个参数chdir ,在帮助文件中描述为:logical; if TRUE and file is a pathname, the R working directory is temporarily changed to the directory containing file for evaluating. 如果为TRUEfile是路径名,则R工作目录将临时更改为包含用于评估的file的目录。

To manually specify that argument every time you want to source a file would be a pain, so let's add something to .Rprofile that changes the default value for chdir from FALSE to TRUE . 要在每次要源文件时手动指定该参数都会很麻烦,所以让我们在.Rprofile中添加一些内容,将chdir的默认值从FALSE更改为TRUE

The formals -function can be used to modify a default value, but when used upon a function that belongs to some other environment, the result will be that a local copy of the function will be created instead. formals -function可用于修改默认值,但是当在属于某个其他环境的函数上使用时,结果将是创建函数的本地副本。 That's not good enough. 这还不够好。

It's probably several ways to resolve this, but the following little hack of source did the trick for me when I inserted it into .Rprofile. 这可能是解决这个问题的几种方法,但是当我将它插入.Rprofile时,下面的一些source就可以解决这个问题。

.temporary_copy_source <- base::source
formals(.temporary_copy_source)$chdir <- TRUE
utils::assignInNamespace(
    x = "source",
    value = .temporary_copy_source,
    ns = environment(source))
rm(.temporary_copy_source)

A word of warning: The method presented here can in principle allow users to modify the default values of any argument in any function, but that would be an exceptionally bad idea to do. 一句警告:此处介绍的方法原则上允许用户修改任何函数中任何参数的默认值,但这样做是一个非常糟糕的主意。 Keep in mind that your scripts might later on be shared with someone that doesn't have the same .Rprofile that you have. 请记住,您的脚本稍后可能会与没有相同.Rprofile的人共享。 Never write code that requires such modifications of the namespaces! 永远不要编写需要对名称空间进行此类修改的代码!

I write another answer because you changed your question. 我写了另一个答案因为你改变了你的问题。 There are two useful facts: 有两个有用的事实:

  1. ofile is a variable in the environment of the source function, so you can use it only when you run some script with the source function. ofilesource函数环境中的变量,因此只有在使用source函数运行某些脚本时才能使用它。
  2. When you run a script from the terminal, then the working directory is set to the current directory in the terminal. 从终端运行脚本时,工作目录将设置为终端中的当前目录。

So, to comment on your observations: 那么,评论你的观察:

  1. Using Rstudio (Works!). 使用Rstudio(Works!)。 Yes if you press Source (which usues the source function), but not if you press Run (which just runs the commands in the R console). 如果按Source (使用source功能),则为Yes,但如果按Run (仅运行R控制台中的命令)则不会。
  2. Rscript writehere.r (Does not work!). Rscript writehere.r(不起作用!)。 That's because you are looking for ofile without a call to source . 那是因为你正在寻找ofile没有到呼叫source
  3. Rscript writehere.r (Works now!). Rscript writehere.r(立即工作!)。 Yes, but it works just by fact 2 : the code this_dir <- function(directory) setwd( file.path(getwd(), directory) ) is needless as it is just the definition of a function called this_dir . 是的,但它只是按事实2工作 :代码this_dir <- function(directory) setwd( file.path(getwd(), directory) )是不必要的,因为它只是一个名为this_dir的函数的定义。
  4. Rstudio (Works!). Rstudio(作品!)。 First part: OK. 第一部分:好的。 Second part. 第二部分。 It works just by fact 2 . 它只是按事实2运作。 In particular setwd_thisdir is needless because it just prints the body of setwd_thisdir to the console. 特别是setwd_thisdir是不必要的,因为它只是将setwd_thisdir的主体打印到控制台。

In summary setwd(dirname(parent.frame(2)$ofile)) is a useful trick when you source a script with the source function, but don't have access to the source function options: eg when you press Source in R-Studio. 总结setwd(dirname(parent.frame(2)$ofile))是一个有用的技巧,当您使用source函数获取脚本,但无法访问source函数选项时:例如,当您在R-中按Source时工作室。 When possible use intead the source function with chdir=TRUE . 如果可能,请使用chdir=TRUEsource函数。 If you run the script form the terminal just set the terminal to the script folder. 如果您运行脚本表单终端只需将终端设置为脚本文件夹。

Simply, use rstudio API, extract its directory, and set it as a working directory as shown below: 简单地说,使用rstudio API,提取其目录,并将其设置为工作目录,如下所示:

setwd(dirname(rstudioapi::getSourceEditorContext()$path))

Verify if you set the directory correctly by the following command: 验证是否通过以下命令正确设置了目录:

getwd()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM