Как я могу использовать setwd относительно? - PullRequest
4 голосов
/ 17 июня 2019

Наша команда использует R-сценарии в git-репозиториях, которые используются несколькими людьми на компьютерах Mac и Windows (и иногда Linux).Это приводит к куче действительно раздражающих строк в верхней части сценариев, которые выглядят так:

#path <- 'C:/data-work/project-a/data'
#path <- 'D:/my-stuff/project-a/data'
path = "~/projects/project-a/data"
#path = 'N:/work-projects/project-a/data'
#path <- "/work/project-a/data"
setwd(path)

Чтобы запустить сценарий, мы должны закомментировать / раскомментировать правильную переменную пути или сценарии выиграли 'Т беги.Это раздражает, неопрятно и имеет тенденцию быть немного беспорядочным в истории коммитов.

Раньше я обходил это с помощью сценариев оболочки для установки каталогов относительно местоположения сценария и пропуска setwdполностью (и затем использовать ./run-scripts.sh вместо Rscript process.R), но, поскольку у нас есть пользователи Windows, это не будет работать.Есть ли лучший способ упростить эти грязные setwd() шаблоны в R?

(примечание: в Python я решаю эту проблему с помощью библиотеки путей, чтобы получить местоположение самого файла сценария, а затем собратьотносительные пути из этого. Но у R, похоже, нет способа узнать местоположение файла запущенного скрипта?)

Ответы [ 3 ]

5 голосов
/ 17 июня 2019

Ответ - вообще не использовать setwd(). R, конечно, немного отличается от Python, но это одна их общая черта.

Вместо этого любые сценарии, которые вы выполняете, должны предполагать, что они запускаются из общей корневой папки верхнего уровня. Когда вы запускаете новый процесс R, его рабочий каталог (т. Е. То, что дает getwd()) устанавливается в ту же папку, из которой был создан процесс.

Например, если у вас был этот макет:

.
├── data
│   └── mydata.csv
└── scripts
    └── analysis.R

Вы будете запускать analysis.R из ., а analysis.R будет ссылаться на data/mydata.csv как "data / mydata.csv" (например, read.csv("data/mydata.csv, stringsAsFactors = FALSE)). Я бы оставил ваши сценарии оболочки или Makefile, которые запускают ваши R-сценарии, и пусть R-сценарии предполагают, что они запускаются с верхнего уровня git репо.

Это может выглядеть так:

cd . # Whereever `.` above is
Rscript scripts/analysis.R

Дополнительное чтение:

1 голос
/ 17 июня 2019

1) Если вы ищете способ найти путь к запущенному в данный момент сценарию, см.

Rscript: определить путь к исполняемому сценарию

2) Другой подход заключается в том, чтобы требовать, чтобы пользователи добавили опцию предварительно назначенного имени в свой файл .Rprofile.Тогда скрипт может setwd к этому.Привлекательным аспектом этой системы является то, что со временем можно забыть, где находятся различные проекты, и с помощью этой системы можно просто взглянуть на файл .Rprofile, чтобы напомнить о себе.Например, для проекта А каждый, кто запускает проект, запишет это в свой файл .Rprofile

options(projectA = "...whatever...")

, а затем скрипт будет начинаться с:

proj <- getOption("projectA")
if (!is.null(proj)) setwd(proj) else stop("Set option 'projectA' to its directory")

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

proj <- getOption("projectA")
if (!is.null(proj)) setwd(proj) else cat("Using", getwd(), "\n")
1 голос
/ 17 июня 2019

в Python, я решаю это, используя библиотеку путей, чтобы получить местоположение самого файла скрипта, а затем строю относительные пути из этого. Но у R, похоже, нет способа узнать местоположение файла запущенного скрипта?

У самого R, к сожалению, нет для этого пути. Но вы можете достичь того же результата любым из двух способов:

  • Используйте пакеты вместо сценариев, где вы включаете код через source. Тогда вы можете использовать решение, изложенное в ответе амебы. Это работает, потому что реальная проблема в том, что R не может сообщить функции source, где искать скрипты.
  • Используйте klmr / modules вместо source. Этот пакет предоставляет систему модулей, которая позволяет относительный импорт модулей кода. Приятным побочным эффектом этого является то, что пакет предоставляет функцию, которая сообщает вам путь к текущему скрипту, как в Python (и, как и в Python, вам обычно не нужно использовать эту функцию напрямую).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...