Je ne fais (probablement) pas référence à la signification de "toutes les autres variables" comme var1~.
ici. J'ai été pointé de nouveau sur plyr
et j'ai examiné mlply
et je me suis demandé pourquoi les paramètres sont définis avec un point de tête comme ceci:
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>
À quoi ça sert? Est-ce simplement une préférence personnelle, une convention de dénomination ou plus? Souvent, R est tellement fonctionnel que je rate un tour qui a été fait depuis longtemps.
Un point dans le nom de la fonction peut signifier l'un des éléments suivants:
Le point dans data.frame
Ne sépare pas data
de frame
, sauf visuellement.
plot
est un exemple de méthode S3 générique. Ainsi, plot.lm
Et plot.glm
Sont les définitions de fonction sous-jacentes utilisées lors de l'appel de plot(lm(...))
ou plot(glm(...))
Lors de l'écriture de packages, il est parfois utile d'utiliser des points de début dans les noms de fonctions car ces fonctions sont quelque peu cachées de la vue générale. Les fonctions censées être purement internes à un package l'utilisent parfois.
Dans ce contexte, "quelque peu caché" signifie simplement que la variable (ou la fonction) n'apparaîtra pas normalement lorsque vous répertoriez un objet avec ls()
. Pour forcer ls
à afficher ces variables, utilisez ls(all.names=TRUE)
. En utilisant un point comme première lettre d'une variable, vous modifiez la portée de la variable elle-même. Par exemple:
x <- 3
.x <- 4
ls()
[1] "x"
ls(all.names=TRUE)
[1] ".x" "x"
x
[1] 3
.x
[1] 4
Dans le package plyr de Hadley, il utilise la convention pour utiliser les points principaux dans les noms de fonction. Il s'agit d'un mécanisme pour essayer de s'assurer que lors de la résolution des noms de variables, les valeurs sont résolues en variables utilisateur plutôt qu'en variables de fonction internes.
Ce méli-mélo d'utilisations différentes peut conduire à des situations très déroutantes, car ces différentes utilisations peuvent toutes se mélanger dans le même nom de fonction.
Par exemple, pour convertir un data.frame
En une liste, vous utilisez as.list(..)
as.list(iris)
Dans ce cas, as.list
Est une méthode générique S3 et vous lui passez un data.frame
. Ainsi, la fonction S3 est appelée as.list.data.frame
:
> as.list.data.frame
function (x, ...)
{
x <- unclass(x)
attr(x, "row.names") <- NULL
x
}
<environment: namespace:base>
Et pour quelque chose de vraiment spectaculaire, chargez le package data.table
Et regardez la fonction 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>
Au début d'un nom, il fonctionne comme la convention de nom de fichier UNIX pour garder les objets cachés par défaut.
ls()
character(0)
.a <- 1
ls()
character(0)
ls(all.names = TRUE)
[1] ".a"
Ce peut être juste un jeton sans signification particulière, il ne fait rien de plus que tout autre jeton autorisé.
my.var <- 1
my_var <- 1
myVar <- 1
Il est utilisé pour l'envoi de la méthode S3. Donc, si je définis une classe simple "maClasse" et que je crée des objets avec cet attribut de classe, les fonctions génériques telles que print () seront automatiquement envoyées vers ma méthode d'impression spécifique.
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)
Il y a une ambiguïté dans la syntaxe de S3, car vous ne pouvez pas dire à partir du nom d'une fonction s'il s'agit d'une méthode S3 ou simplement d'un point dans le nom. Mais, c'est un mécanisme très simple qui est très puissant.
Il y a beaucoup plus à chacun de ces trois aspects, et vous ne devriez pas prendre mes exemples comme bonne pratique, mais ce sont les différences fondamentales.