Подтвердить что ты не робот

Как установить текущее местоположение файла в качестве рабочего каталога по умолчанию в R-программировании?

Я хочу, чтобы текущее местоположение файла было рабочим каталогом.

Использование 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.

Использование команды с терминала: Rscript writehere.r(не работает!)

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


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

Использование команды с терминала: 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")

Использование функции внутри ~/.Rprofile для Rstudio (Works!):,

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

Тогда, в любом каталоге, скажем, у меня есть файл 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")

Вопрос: Почему функция

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

не работает для текстовых редакторов, отличных от Rstudio?

Некоторые полезные ссылки следующие:
R устанавливает рабочий каталог в исходное местоположение файла?
команда R для установки рабочего каталога в исходное расположение файла
 получить имя файла и путь к файлу` source`d
setwd() в текущем рабочем каталоге
Команда для "Установите рабочий каталог в местоположение исходного файла"
SublimeText и R: настройка текущего каталога файлов
Настройка рабочего каталога через функцию
Что такое безупречный способ постоянной установки рабочего каталога R?
R установит рабочий каталог в исходное расположение файла?
Как попасть в каталог файла в R?

4b9b3361

Ответ 1

Попробуйте использовать parent.frame(3) в вашей функции:

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

См. ?parent.frame или http://adv-r.had.co.nz/Environments.html#calling-environments.

Вы также можете посмотреть опцию chdir функции source (?source).

Ответ 2

UPDATE: Я понял, что этот ответ не помог, и я отправлю еще один, который делает трюк.

Если код, который вы хотите запустить, не нуждается в дополнительных аргументах, решение, описанное ниже, используя eval(expr, envir), может сделать трюк.

Рассмотрим следующий пример, используя print(environment()), который должен возвращать environment: R_GlobalEnv при использовании в командной строке. Функция 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)
}

sys.frame(which = -1) гарантирует, что выражение оценивается в среде, где вызывается функция. Если вы уверены, что всегда хотите использовать глобальную среду, лучше использовать .GlobalEnv. Также важно процитировать выражение, которое вы хотите использовать, иначе оно может не работать по желанию.

Хорошей особенностью этого решения является то, что вам не нужно настраивать код, который вы хотите поместить в функцию, просто укажите его.

Наконец: возможно расширить такой подход, чтобы ваша функция могла принимать аргументы, которые затем будут переданы коду, который вы хотите оценить в другой среде. Это, однако, потребует немного нетривиальной настройки для выражения, которое вы хотите оценить; вам может потребоваться использовать конструкцию bquote + .(), и вам также может потребоваться использовать call и do.call.

Ответ 3

Первый ответ, который я дал, полностью пропустил, поскольку у меня не было внимательно посмотрел на то, чего вы хотели достичь. Решение представленный здесь, должен, однако, сделать трюк.

Прежде всего отметим, что source имеет аргумент chdir, который в файле справки описывается с помощью: logical; если TRUE и file - это путь, рабочий каталог R временно изменяется на каталог, содержащий file для оценки.

Чтобы вручную указать этот аргумент каждый раз, когда вы хотите создать файл было бы больно, поэтому добавьте что-то в .Rprofile, который изменит значение по умолчанию для chdir от FALSE до TRUE.

Функция formals может использоваться для изменения значения по умолчанию значение, но при использовании функции, принадлежащей какой-либо другой среда, результатом будет то, что вместо этого будет создана локальная копия функции. Это не очень хорошо.

Возможно, это несколько способов решить эту проблему, но следующие маленький взлом source помогло, когда я вставил его в .Rprofile.

.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)

Слово предупреждения: Представленный здесь метод может в принципе позволяют пользователям изменять значения по умолчанию любого аргумента в любом но это было бы очень плохой идеей. Держать имея в виду, что ваши скрипты позже могут быть переданы кому-то который не имеет того же самого .Rprofile, который у вас есть. Никогда не пишите код, который требует таких модификаций пространств имен!

Ответ 4

Я пишу другой ответ, потому что вы изменили свой вопрос. Есть два полезных факта:

  1. ofile - это переменная в среде функции source, поэтому вы можете использовать ее только при запуске какого-либо скрипта с функцией source.
  2. Когда вы запускаете скрипт из терминала, тогда рабочим каталогом становится текущий каталог в терминале.

Итак, чтобы прокомментировать ваши наблюдения:

  1. Использование Rstudio (Работает!). Да, если вы нажмете Source (который использует функцию source), но не если вы нажмете Run (который просто запускает команды в консоли R).
  2. Rscript напишите здесь .r (не работает!). Это потому, что вы ищете ofile без вызова source.
  3. Rscript writehere.r (работает сейчас!). Да, но это работает просто по факту 2: код this_dir <- function(directory) setwd( file.path(getwd(), directory) ) не нужен, поскольку это просто определение функции под названием this_dir.
  4. Rstudio (Работает!). Первая часть: ОК. Вторая часть. Он работает просто на самом деле 2. В частности, setwd_thisdir не нужен, потому что он просто печатает тело setwd_thisdir на консоли.

Таким образом, setwd(dirname(parent.frame(2)$ofile)) - полезный прием, когда вы создаете сценарий с помощью функции source, но не имеете доступа к опциям функции source: например, когда вы нажимаете Source в R-Studio. По возможности используйте функцию source с помощью chdir=TRUE. Если вы запускаете скрипт из терминала, просто установите терминал в папку скриптов.

Ответ 5

Просто используйте rstudio API, извлеките его каталог и установите его в качестве рабочего каталога, как показано ниже:

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

Проверьте правильность установки каталога с помощью следующей команды:

getwd()