Что означает точка в R - личные предпочтения, соглашение об именах или более?
Я (вероятно) не имею в виду "все другие переменные", что означает var1~.
Вот. Мне указали на plyr
еще раз и посмотрел в mlply
и задавался вопросом, почему параметры определяются с начальной точкой, как это:
function (.data, .fun = NULL, ..., .expand = TRUE, .progress = "none",
.parallel = FALSE)
{
if (is.matrix(.data) & !is.list(.data))
.data <- .matrix_to_df(.data)
f <- splat(.fun)
alply(.data = .data, .margins = 1, .fun = f, ..., .expand = .expand,
.progress = .progress, .parallel = .parallel)
}
<environment: namespace:plyr>
Какая польза от этого? Это просто личные предпочтения, соглашение об именах или больше? Часто R настолько функционален, что я пропускаю трюк, который давно уже был сделан.
2 ответа
Точка в имени функции может означать любое из следующего:
- вообще ничего
- разделитель между методом и классом в методах S3
- скрыть имя функции
Возможные значения
1. вообще ничего
Точка в data.frame
не отделяется data
от frame
кроме визуально.
2. Разделение методов и классов в методах S3
plot
один пример универсального метода S3. таким образом plot.lm
а также plot.glm
являются основными определениями функций, которые используются при вызове plot(lm(...))
или же plot(glm(...))
3. Спрятать внутренние функции
При написании пакетов иногда полезно использовать начальные точки в именах функций, потому что эти функции несколько скрыты от общего вида. Функции, которые должны быть чисто внутренними для пакета, иногда используют это.
В этом контексте "несколько скрытый" просто означает, что переменная (или функция) обычно не отображается, когда вы перечисляете объект с ls()
, Чтобы заставить ls
чтобы показать эти переменные, используйте ls(all.names=TRUE)
, Используя точку в качестве первой буквы переменной, вы изменяете область действия самой переменной. Например:
x <- 3
.x <- 4
ls()
[1] "x"
ls(all.names=TRUE)
[1] ".x" "x"
x
[1] 3
.x
[1] 4
4. Другие возможные причины
В пакете plyr Хэдли он использует соглашение, чтобы использовать начальные точки в именах функций. Это как механизм, позволяющий убедиться, что при разрешении имен переменных значения разрешаются для пользовательских переменных, а не для внутренних переменных функций.
осложнения
Эта путаница различных применений может привести к очень запутанным ситуациям, потому что все эти разные варианты использования могут смешиваться в одном и том же имени функции.
Например, чтобы преобразовать data.frame
в список, который вы используете as.list(..)
as.list(iris)
В этом случае as.list
является общим методом S3, и вы передаете data.frame
к этому. Таким образом, функция S3 называется as.list.data.frame
:
> as.list.data.frame
function (x, ...)
{
x <- unclass(x)
attr(x, "row.names") <- NULL
x
}
<environment: namespace:base>
И для чего-то действительно впечатляющего, загрузите data.table
упаковать и посмотреть на функцию as.data.table.data.frame
:
> library(data.table)
> methods(as.data.table)
[1] as.data.table.data.frame* as.data.table.data.table* as.data.table.matrix*
Non-visible functions are asterisked
> data.table:::as.data.table.data.frame
function (x, keep.rownames = FALSE)
{
if (keep.rownames)
return(data.table(rn = rownames(x), x, keep.rownames = FALSE))
attr(x, "row.names") = .set_row_names(nrow(x))
class(x) = c("data.table", "data.frame")
x
}
<environment: namespace:data.table>
В начале имени это работает как соглашение об имени файла UNIX, чтобы скрыть объекты по умолчанию.
ls()
character(0)
.a <- 1
ls()
character(0)
ls(all.names = TRUE)
[1] ".a"
Это может быть просто токен без особого значения, он не делает ничего больше, чем любой другой разрешенный токен.
my.var <- 1
my_var <- 1
myVar <- 1
Используется для отправки по методу S3. Таким образом, если я определю простой класс "myClass" и создам объекты с этим атрибутом класса, то универсальные функции, такие как print(), автоматически отправят мой конкретный метод печати.
myvar <- 1
print(myvar)
class(myvar) <- c("myClass", class(myvar))
print.myClass <- function(x, ...) {
print(paste("a special message for myClass objects, this one has length", length(x)))
return(invisible(NULL))
}
print(myvar)
В синтаксисе S3 существует неоднозначность, поскольку по имени функции невозможно определить, является ли это методом S3 или просто точкой в имени. Но это очень простой механизм, который очень мощный.
В каждом из этих трех аспектов есть намного больше, и вы не должны воспринимать мои примеры как хорошую практику, но они являются основными отличиями.
Если пользователь определяет функцию.doSomething и ленится указать всю документацию roxygen для параметров, он не будет генерировать ошибки для компиляции пакета.