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

Риски использования setwd() в script?

Я слышал, что это говорит о том, что использовать setwd() в script - это плохая практика.

  • Каковы риски/опасности, связанные с этим?
  • Каковы лучшие альтернативы?
4b9b3361

Ответ 1

Это проблема воспроизводимого кода. Если вы укажете каталог, который не существует на другом компьютере, они не смогут использовать ваш код. Это особенно плохо с абсолютными путями файлов и особенно плохо с файловыми путями Windows (которые абсолютно невозможно реплицировать в системе Unix).

Мое предпочтительное решение - указать, что перед запуском кода пользователь должен находиться в соответствующем каталоге в своей собственной системе. Если для вашего удобства вы хотите разместить setwd(...) справа вверху своего кода, где другие люди могут его заметить и прокомментировать, если это необходимо, но остальная часть вашего кода предполагает только относительные пути из этого стартового каталога, что Хорошо со мной.

Yihui Xie (автор knitr) особенно сильно относится к этому:

https://groups.google.com/forum/?fromgroups=#!topic/knitr/knM0VWoexT0

Всякий раз, когда вы хотите манипулировать файлами, предполагается, что они находятся под тот же каталог вашего источника (например, документы Rnw). Тогда ты можешь всегда используйте относительные пути, и вам никогда не понадобится setwd(). С помощью setwd() противоречит принципу воспроизводимости, например. вы используйте setwd ('foo/bar/'), и каталог может отсутствовать в другом люди компьютеры. См. FAQ 7: https://github.com/yihui/knitr/blob/master/FAQ.md

И из вышеупомянутого FAQ 7:

Лучше не делать этого [изменить рабочий каталог внутри кода knitr ломти]. В вашем рабочем каталоге всегда есть getwd() (все выходные файлы будут написаны здесь), но фрагменты кода оцениваются в соответствии с каталог, откуда приходит ваш входной документ. Изменение рабочих каталоги во время работы R-кода являются плохой практикой в ​​целом. См. № 38 для обсуждения. Вы также должны избегать абсолютных каталогов когда это возможно (используйте вместо этого относительные каталоги), поскольку это делает вещи, менее воспроизводимые.

Смотрите также: https://github.com/yihui/knitr/issues/38

Ответ 2

Я не могу думать о каких-либо особых проблемах с использованием setwd() в script на сервере, которым я управляю, поскольку он возвращает ошибку, которая может быть захвачена с помощью try(), и вы можете управлять им. Я использовал setwd(), когда лгал о путях - см. Ниже!

Я использую file.path() широко в создании скриптов или иначе. Работа с файлами во входном каталоге и размещение выходной графики и отчетов в другом месте. Итак, что-то вроде строк... (untested) Это было бы немного утомительно, используя setwd().

kInDir <- '~/Indir'
kOutDir <- '~/Outdir'
flist <- dir(path=kInDir, pattern='^[a-z]{2,5}\\.csv$')
# note I could have used full.names=T - but it easier not to...
for (fnam in flist) {
  # full path to the report file created
  sfnam <- file.path(kOutDir, gsub('.csv', '_report.txt', fnam))
  # full path to the csv file that will be created
  ofnam <- file.path(kOutDir, gsub('.csv', '_b.csv', fnam))
  #
  # ok... we're going to process this CSV file...
  r1 <- read.csv(file.path(kInDir, fnam))
  #
  # we''ll put the output from the analysis into this report file
  sink(sfnam, split=TRUE)
  # processs it... into a new data.frame k1
  # blah blah blah...
  #
  write.csv(k1, file=ofnam, row.names=FALSE)
  sink() # turn off this particular report file
}

Ответ 3

К лучшему альтернативному вопросу:

В основном я использую R для отдельных проектов (это означает, что я являюсь основным аналитиком). Однако мы используем их в проектах, которые иногда нужно делиться с другими.

RStudio - Проекты

Я обнаружил, что функциональность RStudio 's Projects имеет большое значение для организации ваших файлов. Если другие пользователи также принимают RStudio, у них будет приятное ощущение, что вы сможете открыть один файл ("*.Rproj") и загрузить проект в том же состоянии, в котором вы его последний раз сохранили.

ProjectTemplate

Кроме того, я нашел новый инструмент, ProjectTemplate, который идет дальше! Техника, разработанная автором, используется для обеспечения структуры того, что вы делаете. Перейдите на сайт для более подробной информации.

Ответ 4

Несмотря на то, что проблемы с setwd() были нацелены, я хотел бы добавить еще одно к тому, что является альтернативной частью вопроса. Мы часто работаем с git, где относительный путь очень удобен

setrelwd <- function(rel_path){
  curr_dir <- getwd()
  abs_path <- file.path(curr_dir,rel_path)
  if(dir.exists(abs_path)){
    setwd(abs_path)
  }
  else
  {
    warning('Directory does not exist. Please create it first.')
  }

}

> setrelwd("Summer2016")
Warning message:
In setrelwd("Summer2016") : Directory does not exist. Please create it first.

Также, если вы не хотите видеть предупреждающее сообщение, но сразу создаете папку, см. Проверить наличие директории и создать, если она не существует

Ответ 5

Чтобы сделать вещи более переносимыми, когда я работаю, все мы помещаем это в Rprofile

hdrive=
switch(Sys.info()[[1]],
'Linux'="/mnt/hdrive",
'Windows'="H:/",
"Darwin"="/Volumes/hdrive/mnt/hdrive"
)

Итак, у меня всегда есть эта переменная, чтобы получить меня на нашем общем диске. Затем в моем script мы можем написать

setwd(paste(hdrive,"/relative/path/",sep="/"))

Таким образом, мы получаем некоторые проблемы, о которых говорят другие.

Ответ 6

Я лично добавил следующий код. Я использую Sys.info() и any() с уникальной информацией.

Первый шаг - использовать Sys.info() и найти уникальный идентификатор для вашего компьютера.

if(any(Sys.info() == "COMPUTER1")) {
  setwd("c:/Users/user1/repos/project/")
}

if(any(Sys.info() == "COMPUTER2")) {
  setwd("home/user1/repos/project/")
}

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

Для воспроизведения это не изменяет ни одну рабочую директорию, если они не являются этим конкретным пользователем.