web-dev-qa-db-fra.com

Que signifie le point dans R - préférence personnelle, convention de dénomination ou plus?

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.

70
Matt Bannert

Un point dans le nom de la fonction peut signifier l'un des éléments suivants:

  • rien du tout
  • un séparateur entre méthode et classe dans les méthodes S3
  • masquer le nom de la fonction

Significations possibles

1. Rien du tout

Le point dans data.frame Ne sépare pas data de frame, sauf visuellement.

2. Séparation des méthodes et des classes dans les méthodes S3

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(...))

3. Pour masquer les fonctions internes

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

4. Autres raisons possibles

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.


Complications

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>
107
Andrie

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.

27
mdsumner