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

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

Использование Rstudio (Работает!):

# 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 (Работает!):,

##############################################
# 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?

4 ответа

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

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

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

getwd()

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

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

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

  1. Использование Rstudio (Работает!). Да, если вы нажмете Источник (который использует 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. По возможности используйте intead source функция с chdir=TRUE, Если вы запускаете скрипт из терминала, просто установите терминал в папку скриптов.

Попробуйте использовать 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.

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

ОБНОВЛЕНИЕ: я понял, что этот ответ не помог вообще, и я опубликую другой, который делает трюк.

Поскольку код, который вы хотите запустить, не нуждается в дополнительных аргументах, решение, как показано ниже, с использованием 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,

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

Первое замечание, что source есть аргумент chdir что в справочном файле описано с помощью: логического; если 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, что у вас есть. Никогда не пишите код, который требует таких модификаций пространств имен!

Другие вопросы по тегам