Я слышал, что это говорит о том, что использовать setwd()
в script - это плохая практика.
- Каковы риски/опасности, связанные с этим?
- Каковы лучшие альтернативы?
Я слышал, что это говорит о том, что использовать setwd()
в script - это плохая практика.
Это проблема воспроизводимого кода. Если вы укажете каталог, который не существует на другом компьютере, они не смогут использовать ваш код. Это особенно плохо с абсолютными путями файлов и особенно плохо с файловыми путями 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
Я не могу думать о каких-либо особых проблемах с использованием 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
}
К лучшему альтернативному вопросу:
В основном я использую R для отдельных проектов (это означает, что я являюсь основным аналитиком). Однако мы используем их в проектах, которые иногда нужно делиться с другими.
Я обнаружил, что функциональность RStudio 's Projects имеет большое значение для организации ваших файлов. Если другие пользователи также принимают RStudio, у них будет приятное ощущение, что вы сможете открыть один файл ("*.Rproj") и загрузить проект в том же состоянии, в котором вы его последний раз сохранили.
Кроме того, я нашел новый инструмент, ProjectTemplate, который идет дальше! Техника, разработанная автором, используется для обеспечения структуры того, что вы делаете. Перейдите на сайт для более подробной информации.
Несмотря на то, что проблемы с 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.
Также, если вы не хотите видеть предупреждающее сообщение, но сразу создаете папку, см. Проверить наличие директории и создать, если она не существует
Чтобы сделать вещи более переносимыми, когда я работаю, все мы помещаем это в Rprofile
hdrive=
switch(Sys.info()[[1]],
'Linux'="/mnt/hdrive",
'Windows'="H:/",
"Darwin"="/Volumes/hdrive/mnt/hdrive"
)
Итак, у меня всегда есть эта переменная, чтобы получить меня на нашем общем диске. Затем в моем script мы можем написать
setwd(paste(hdrive,"/relative/path/",sep="/"))
Таким образом, мы получаем некоторые проблемы, о которых говорят другие.
Я лично добавил следующий код. Я использую 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 и добавьте правильный путь. Просто добавьте новое, если для каждой машины.
Для воспроизведения это не изменяет ни одну рабочую директорию, если они не являются этим конкретным пользователем.