Вопрос

Когда я берусь за R-проект любой сложности, мои сценарии быстро становятся длинными и запутанными.

Какие приемы я могу использовать, чтобы с моим кодом всегда было приятно работать?Я думаю о таких вещах, как

  • Размещение функций в исходных файлах
  • Когда нужно вынести что-то в другой исходный файл
  • Что должно быть в мастер-файле
  • Использование функций в качестве организационных единиц (стоит ли это, учитывая, что R затрудняет доступ к глобальному состоянию)
  • Практика отступов/разрыва строк.
    • Относиться (как {?
    • Поместите такие вещи, как )} в 1 или 2 строки?

По сути, каковы ваши практические правила организации больших сценариев R?

Это было полезно?

Решение

Стандартный ответ — использовать пакеты — см. Написание расширений R руководство, а также различные учебные пособия в Интернете.

Это дает вам

  • квазиавтоматический способ организовать код по темам
  • настоятельно рекомендует написать файл помощи, заставляющий задуматься об интерфейсе
  • много проверок работоспособности через R CMD check
  • возможность добавить регрессионные тесты
  • а также средство для пространств имен.

Просто бегу source() over code работает для очень коротких фрагментов.Все остальное должно быть в пакете — даже если вы не планируете его публиковать, поскольку вы можете писать внутренние пакеты для внутренних репозиториев.

Что касается части «как редактировать», то Внутреннее устройство R инструкция имеет отличный Стандарты кодирования R в разделе 6.В противном случае я склонен использовать значения по умолчанию в Режим ESS Emacs.

Обновление от 13 августа 2008 г.: Дэвид Смит только что написал в блоге о Руководство по стилю Google R.

Другие советы

Мне нравится помещать разные функции в свои файлы.

Но мне не нравится система пакетов R.Его довольно сложно использовать.

Я предпочитаю облегченную альтернативу: разместить функции файла внутри среды (то, что любой другой язык называет «пространством имен») и прикрепить их.Например, я создал группу функций «util» следующим образом:

util = new.env()

util$bgrep = function [...]

util$timeit = function [...]

while("util" %in% search())
  detach("util")
attach(util)

Это все в файле util.R.Когда вы получаете его, вы получаете среду «util», чтобы вы могли вызывать util$bgrep() и тому подобное;но, кроме того, attach() звонок делает это таким простым bgrep() и такая работа напрямую.Если бы вы не поместили все эти функции в их собственную среду, они загрязнили бы пространство имен верхнего уровня интерпретатора (то, которое ls() шоу).

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

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

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

Насколько мелко/грубо вы делаете свои функции, будет варьироваться, и существуют различные эмпирические правила:например15 строк кода или «функция должна отвечать за выполнение одной задачи, которая определяется ее именем» и т. д.Ваш пробег будет отличаться.Поскольку R не поддерживает вызов по ссылке, я обычно стараюсь делать свои функции слишком детализированными, когда они связаны с передачей кадров данных или подобных структур.Но это может быть чрезмерной компенсацией некоторых глупых ошибок производительности, когда я впервые начал работать с R.

Когда извлекать логические единицы в отдельные физические единицы (например, исходные файлы или более крупные группы, например пакеты)?У меня есть два случая.Во-первых, если файл становится слишком большим и прокрутка между логически несвязанными модулями раздражает.Во-вторых, если у меня есть функции, которые могут повторно использоваться другими программами.Обычно я начинаю с помещения какого-нибудь сгруппированного модуля, например функций манипулирования данными, в отдельный файл.Затем я могу получить этот файл из любого другого сценария.

Если вы собираетесь развертывать свои функции, вам нужно подумать о пакетах.Я не развертываю код R в производстве или для повторного использования другими по разным причинам (кратко:организационная культура предпочитает другие языки, заботится о производительности, GPL и т. д.).Кроме того, я склонен постоянно совершенствовать и пополнять свои коллекции исходных файлов, и я предпочитаю не иметь дело с пакетами, когда вношу изменения.Поэтому вам следует ознакомиться с другими ответами, связанными с пакетами, например, с Дирком, для получения более подробной информации на этом фронте.

Наконец, я думаю, что ваш вопрос не обязательно касается Р.Я бы очень рекомендовал прочитать Code Complete Стива МакКоннелла, в котором содержится много мудрости по таким вопросам и практикам кодирования в целом.

Я согласен с советом Дирка!ИМХО, организация ваших программ из простых сценариев в документированные пакеты - это для программирования на R все равно, что переключиться с Word на TeX/LaTeX для написания.Рекомендую взглянуть на очень полезное Создание пакетов R:Учебное пособие Фридрих Лейш.

Мой краткий ответ:

  1. Тщательно пишите свои функции, определяя достаточно общие выходные и входные данные;
  2. Ограничьте использование глобальных переменных;
  3. Используйте объекты S3 и, при необходимости, объекты S4;
  4. Поместите функции в пакеты, особенно если ваши функции вызывают C/Fortran.

Я считаю, что R все больше и больше используется в производстве, поэтому потребность в повторно используемом коде больше, чем раньше.Я считаю, что переводчик гораздо более надежный, чем раньше.Нет сомнений в том, что R в 100–300 раз медленнее C, но обычно узкое место концентрируется вокруг нескольких строк кода, которые можно делегировать C/C++.Я думаю, было бы ошибкой делегировать сильные стороны R в манипулировании данными и статистическом анализе другому языку.В этих случаях снижение производительности невелико и в любом случае стоит экономии усилий по разработке.Если бы дело было только во времени выполнения, мы бы все писали на ассемблере.

Я хотел понять, как писать пакеты, но не потратил на это времени.Для каждого из моих мини-проектов я храню все свои низкоуровневые функции в папке под названием «functions/» и помещаю их в отдельное пространство имен, которое я явно создаю.

Следующие строки кода создадут среду с именем «myfuncs» на пути поиска, если она еще не существует (с помощью Attach), и заполнят ее функциями, содержащимися в файлах .r в моем каталоге «функции/» (с помощью sys.источник).Обычно я помещаю эти строки в начало моего основного скрипта, предназначенного для «пользовательского интерфейса», из которого вызываются функции высокого уровня (вызывающие функции низкого уровня).

if( length(grep("^myfuncs$",search()))==0 )
  attach("myfuncs",pos=2)
for( f in list.files("functions","\\.r$",full=TRUE) )
  sys.source(f,pos.to.env(grep("^myfuncs$",search())))

Когда вы вносите изменения, вы всегда можете повторно использовать их с теми же строками или использовать что-то вроде

evalq(f <- function(x) x * 2, pos.to.env(grep("^myfuncs$",search())))

для оценки дополнений/модификаций в созданной вами среде.

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

Что касается соглашений о кодировании, это единственное, что я видел в отношении эстетики (они мне нравятся, и я свободно им следую, но я не использую слишком много фигурных скобок в R):

http://www1.maths.lth.se/help/R/RCC/

Существуют и другие «соглашения» относительно использования [,drop=FALSE] и <-, как предлагалось в различных презентациях (обычно основных) на сайте useR!конференциях, но я не думаю, что какой-либо из них является строгим (хотя [,drop=FALSE] полезен для программ, в которых вы не уверены в ожидаемом вводе).

Считайте меня еще одним человеком, выступающим за пакеты.Я признаю, что довольно плохо умею писать справочные страницы и эпизоды до тех пор, пока мне это не понадобится (т. е. не будет выпущен), но это действительно удобный способ объединить исходный код doe.Кроме того, если вы серьезно относитесь к поддержке своего кода, все моменты, которые поднимает Дирк, войдут в силу.

Я тоже согласен.Для начала используйте функцию package.skeleton().Даже если вы считаете, что ваш код, возможно, никогда больше не будет запущен, это может побудить вас создать более общий код, который впоследствии сэкономит вам время.

Что касается доступа к глобальной среде, это легко сделать с помощью оператора <<-, хотя это и не рекомендуется.

Еще не научившись писать пакеты, я всегда организовывал работу с помощью дополнительных сценариев.Это похоже на уроки письма, но не так сложно.Это не программно элегантно, но я обнаружил, что со временем накапливаю анализ.Если у меня есть большой работающий раздел, я часто перемещаю его в другой скрипт и просто использую исходный код, поскольку он будет использовать объекты рабочей области.Возможно, мне нужно импортировать данные из нескольких источников, отсортировать их все и найти пересечения.Я мог бы поместить этот раздел в дополнительный сценарий.Однако, если вы хотите распространять свое «приложение» для других людей или оно использует какой-либо интерактивный ввод, пакет, вероятно, будет хорошим вариантом.Как исследователю мне редко приходится распространять свой аналитический код, но мне ЧАСТО нужно его дополнить или настроить.

Я также искал Святой Грааль правильного рабочего процесса для создания большого проекта R.В прошлом году я нашел этот пакет под названием номер, и, конечно же, это было то, что я искал.Этот пакет R был специально разработан для развертывания крупных проектов R, но я обнаружил, что его можно использовать для проектов R меньшего, среднего и большого размера.Я дам ссылки на реальные примеры через минуту (ниже), но сначала я хочу объяснить новую парадигму создания проектов R с помощью rsuite.

Примечание.Я не создатель и не разработчик rsuite.

  1. Мы неправильно выполняли проекты с RStudio;целью должно быть создание не проекта или пакета, а более широкого масштаба.В rsuite вы создаете суперпроект или главный проект, который содержит стандартные проекты R и пакеты R во всех возможных комбинациях.

  2. Имея суперпроект R, вам больше не нужен Unix. make управлять нижними уровнями нижестоящих проектов R;вы используете сценарии R вверху.Позволь мне показать тебе.Когда вы создаете главный проект rsuite, вы получаете следующую структуру папок:

enter image description here

  1. Папка R здесь вы размещаете свои сценарии управления проектами, те, которые заменят make.

  2. Папка packages это папка, где rsuite содержит все пакеты, составляющие суперпроект.Вы также можете скопировать и вставить пакет, который недоступен из Интернета, и rsuite также его соберет.

  3. Папка deployment это здесь rsuite напишет все бинарники пакетов, которые были указаны в пакетах DESCRIPTION файлы.Таким образом, это само по себе делает ваш проект полностью воспроизводимым во времени.

  4. rsuite поставляется с клиентом для всех операционных систем.Я протестировал их все.Но вы также можете установить его как addin для RStudio.

  5. rsuite также позволяет построить изолированный conda установка в свою папку conda.Это не среда, а физическая установка Python, полученная из Anaconda, на вашем компьютере.Это работает вместе с R SystemRequirements, из которого вы можете установить все нужные вам пакеты Python из любого канала conda.

  6. Вы также можете создавать локальные репозитории для извлечения пакетов R, когда вы находитесь в автономном режиме, или хотите собрать все быстрее.

  7. При желании вы также можете создать проект R в виде zip-файла и поделиться им с коллегами.Он будет работать, если у ваших коллег установлена ​​та же версия R.

  8. Другой вариант — создать контейнер всего проекта в Ubuntu, Debian или CentOS.Таким образом, вместо того, чтобы делиться zip-файлом со сборкой проекта, вы делитесь всей Docker контейнер с вашим проектом, готовым к запуску.

Я много экспериментировал с rsuite стремитесь к полной воспроизводимости и избегайте зависимости от пакетов, которые устанавливаются в глобальной среде.Это неправильно, потому что как только вы устанавливаете обновление пакета, проект, чаще всего, перестает работать, особенно те пакеты, которые имеют очень специфические вызовы функции с определенными параметрами.

Первое, с чем я начал экспериментировать, было с bookdown электронные книги.Мне никогда не удавалось иметь книгу, которая выдерживала бы испытание временем дольше шести месяцев.Итак, я преобразовал исходный проект bookdown в соответствии с rsuite рамки.Теперь мне не нужно беспокоиться об обновлении глобальной среды R, поскольку у проекта есть собственный набор пакетов в deployment папка.

Следующее, что я сделал, — это создал проекты машинного обучения, но в rsuite способ.Мастер, управляющий проектом наверху, а все подпроекты и пакеты должны находиться под контролем мастера.Это действительно меняет способ написания кода на R, делая вашу работу более продуктивной.

После этого я начал работать над новым пакетом под названием rTorch.Это стало возможным во многом благодаря rsuite;это позволяет вам думать и действовать масштабно.

Однако один совет.Обучение rsuite нелегко.Поскольку он представляет новый способ создания проектов R, он кажется трудным.Не расстраивайтесь при первых попытках, продолжайте подниматься по склону, пока не добьетесь успеха.Это требует глубоких знаний вашей операционной системы и файловой системы.

Я ожидаю, что однажды RStudio позволяет нам создавать оркестровочные проекты, такие как rsuite делает из меню.Это было бы замечательно.

Ссылки:

Репозиторий RSuite на GitHub

книга r4ds

Керас и блестящее руководство

Moderndive-book-rsuite

интерпретируемый_ml-rsuite

ВведениеМашинное обучениесR-rsuite

clark-intro_ml-rsuite

Hyndman-bookdown-rsuite

статистический_rethinking-rsuite

fread-benchmarks-rsuite

dataviz-rsuite

розничная сегментация-h2o-учебник

Учебное пособие по оттоку клиентов телекоммуникационной компании

sclerotinia_rsuite

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top