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

R стиль записи - требуется vs.::

Хорошо, мы все знакомы с оператором двойной толпы в R. Когда я собираюсь написать какую-то функцию, я использую require(<pkgname>), но я всегда думал об использовании ::. Использование require в пользовательских функциях лучше, чем library, поскольку require возвращает предупреждение и FALSE, в отличие от library, который возвращает ошибку, если вы указываете имя несуществующего пакета.

С другой стороны, оператор :: получает переменную из пакета, а require загружает весь пакет (по крайней мере, я надеюсь, что так), поэтому на мой взгляд возникли различия в скорости. :: должен быть быстрее, чем require.

И я сделал некоторый анализ, чтобы проверить это - я написал две простые функции, которые загружают функцию read.systat из пакета foreign, с require и :: соответственно, поэтому импортируйте набор данных Iris.syd, который корабли с пакетом foreign, реплицированные функции 1000 раз каждый (что было бесстыдно произвольно) и... хрустели некоторые цифры.

Странно (или нет) я обнаружил существенные различия с точки зрения пользовательского процессора и прошедшего времени, тогда как существенных различий в системном процессоре не было. И еще более странный вывод: :: на самом деле медленнее! Документация для :: очень тупая, и, просто взглянув на источники, очевидно, что :: должен работать лучше!

требуется

#!/usr/local/bin/r

## with require
fn1 <- function() {
  require(foreign)
  read.systat("Iris.syd", to.data.frame=TRUE)
}

## times
n <- 1e3

sink("require.txt")
print(t(replicate(n, system.time(fn1()))))
sink()

двойной двоеточие

#!/usr/local/bin/r

## with ::
fn2 <- function() {
  foreign::read.systat("Iris.syd", to.data.frame=TRUE)
}

## times
n <- 1e3


sink("double_colon.txt")
print(t(replicate(n, system.time(fn2()))))
sink()

Возьмите CSV-данные здесь. Некоторая статистика:

user CPU:     W = 475366    p-value = 0.04738  MRr =  975.866    MRc = 1025.134
system CPU:   W = 503312.5  p-value = 0.7305   MRr = 1003.8125   MRc =  997.1875
elapsed time: W = 403299.5  p-value < 2.2e-16  MRr =  903.7995   MRc = 1097.2005

MRr - средний ранг для require, MRc ibid для ::. Я, должно быть, сделал что-то не так. Это просто не имеет никакого смысла... Время выполнения для :: кажется быстрее! Возможно, я что-то прикрутил, вы не должны отбрасывать этот вариант...

ОК... Я потратил свое время, чтобы увидеть, что есть какая-то разница, и я провел совершенно бесполезный анализ, поэтому вернемся к вопросу:

"Зачем нужно писать require над :: при записи функции?"

=)

4b9b3361

Ответ 1

"Зачем нужно больше: при написании функции?"

Я обычно предпочитаю require из-за хорошего возвращаемого значения TRUE/FALSE, которое позволяет мне иметь дело с возможностью того, чтобы пакет не был доступен перед тем, как попасть в код. Сбой как можно раньше, а не на полпути через ваш анализ.

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

С другой стороны,:: оператор получает переменная из пакета, в то время как требуют загрузки всего пакета (не менее Надеюсь, что так), поэтому произошли перемены скорости сначала на мой взгляд.:: должен быть быстрее чем требуется.

Я думаю, что вы можете игнорировать эффекты ленивой загрузки, которые используются пакетом foreign в соответствии с первой страницей своего руководства, По сути, пакеты, которые используют ленивую загрузку, откладывают загрузку объектов, таких как функции, до тех пор, пока объекты не будут вызваны в первый раз. Поэтому ваш аргумент о том, что ":: должен быть быстрее, чем требуется", не обязательно истинен, поскольку foreign не загружает все его содержимое в память, когда вы прикрепляете его с помощью require. Полную информацию о ленивой загрузке см. Prof. Статья Рипли в номере RNews, том 4, выпуск 2.

Ответ 2

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

Для скриптов, имеющих вызов require или library в начале, вы можете сразу узнать, какие пакеты вам нужны.

Аналогично, вызов require (или обертка типа requirePackage в Hmisc или try_require в ggplot2) в начале функции - это самый однозначный способ показать, что вам нужно использовать этот пакет.

:: должен быть зарезервирован для случаев, когда у вас есть конфликты имен между пакетами – сравните, например,

Hmisc::is.discrete

и

plyr::is.discrete