table() avec argument row.names

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Eric Wajnberg
Messages : 776
Enregistré le : 11 Aoû 2008, 15:37
Contact :

table() avec argument row.names

Messagepar Eric Wajnberg » 13 Sep 2018, 11:27

Bonjour à tous,

Il y a un truc que je ne comprends avec avec table(). Voici un exemple :

Code : Tout sélectionner

> # un premier vecteur
> x
[1] 2 5 5 4 2
> # un deuxième vecteur qui est un facteur
> y
[1] a b b a a
Levels: a b
> # je veux construire une contingence sur x en utilisant les noms des niveaux du facteur y
> table(x,row.names=y)
   row.names
x   a b
  2 2 0
  4 1 0
  5 0 2

Jusque là tout va bien. Cependant, j'ai deux questions.

1) Si on remplace "row.names" par n'importe quoi d'autre, ca marche pareil :

Code : Tout sélectionner

> table(x,forum.R=y)
   forum.R
x   a b
  2 2 0
  4 1 0
  5 0 2

Comment est-ce possible ? Comment un argument dont le nom n'a rien à voir est reconnu comme un argument ayant un nom différent. C'est contraire à la syntaxe de R, et même- du coup - source d'erreurs possibles. J'ai loupé quelque chose ?

2) L'autre question est comment se débarrasser de la sortie du nom de cet argument dans la première ligne ?

Tout aide/explication sur ces deux points est la bienvenue.

Eric.

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: table() avec argument row.names

Messagepar Logez Maxime » 13 Sep 2018, 11:57

Bonjour,

ça vient de la manière dont sont gérés les arguments de la fonction table. Si tu fais args(table) tu verras ceci :

Code : Tout sélectionner

function (..., exclude = if (useNA == "no") c(NA, NaN), useNA = c("no",
    "ifany", "always"), dnn = list.names(...), deparse.level = 1)

Par conséquent tous les arguments qui seront placés avant les arguments nommés (exclude, useNA, etc.) seront pris dans le '...' et garderont leurs noms. Donc si tu fais table(x, row.names=y), les deux premiers arguments sont x et row.names.
Au début de la fonction table tu peux voir cette commande :

Code : Tout sélectionner

args <- list(...)
Qui permet de récupéré les arguments que tu as passés dans la fonction dans une liste :

Code : Tout sélectionner

f1 <- function(...) {
  args <- list(...)
  print(args)
  }

x <- 1:4
y <- gl(2,2)
f1(x, row.names = y)
[1]]
[1] 1 2 3 4

$row.names
[1] 1 1 2 2
Levels: 1 2
Tu vois que le deuxième élément de cette liste a pour nom row.names et c'est celui ci qu'il va utiliser par la suite. De plus il y a la fonction list.names au sein de la fonction table qui permet de récupérer le nom des arguments qui se trouvent dans les '...' :

Code : Tout sélectionner

f1 <- function(..., deparse.level = 1) {
  list.names <- function(...) {
    l <- as.list(substitute(list(...)))[-1L]
    nm <- names(l)
    fixup <- if (is.null(nm))
      seq_along(l)
    else nm == ""
    dep <- vapply(l[fixup], function(x) switch(deparse.level +
                                                 1, "", if (is.symbol(x)) as.character(x) else "",
                                               deparse(x, nlines = 1)[1L]), "")
    if (is.null(nm))
      dep
    else {
      nm[fixup] <- dep
      nm
    }
  }
 
  nm <- list.names(...)
  print(nm)
}
f1(x, row.names = y)
[1] "x"         "row.names"
D'où ton résultat.

Cordialement,
Maxime

Eric Wajnberg
Messages : 776
Enregistré le : 11 Aoû 2008, 15:37
Contact :

Re: table() avec argument row.names

Messagepar Eric Wajnberg » 13 Sep 2018, 12:05

Très clair, merci Maxime, mais ça ne me dit pas :

1) Pourquoi mon argument de nom quelconque est utilisé (fonctionnellement) comme l'argument row.names, et
2) Comment se débarrasser de la sortie du nom de cet argument dans la première ligne de sortie de l'appel à la fonction table()?

Encore merci pour la disponibilité !

Eric.

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: table() avec argument row.names

Messagepar Logez Maxime » 13 Sep 2018, 12:43

Eric Wajnberg a écrit :1) Pourquoi mon argument de nom quelconque est utilisé (fonctionnellement) comme l'argument row.names, et
2) Comment se débarrasser de la sortie du nom de cet argument dans la première ligne de sortie de l'appel à la fonction table()?
1) parce que fonctionnellement les ... sont placés en premier argument. Du coup avec les '...' tu peux lui mettre tout et n'importe quoi, le nom n'a pas d'importance mais sera traduit tel quel. Du moment ou tu lui mets a = b, alors 'a' sera le nom de ton argument et b sa valeur vu que tout ce qui est dans les '...' sera intégré dans une liste. C'est comme si tu écrivais list(x, row.names = y) donc tu as une liste à deux éléments, le premier sans nom mais qui sera retrouvé grâce à la fonction list.names et le deuxième aura pour nom row.names et pour valeur y.
2) en modifiant le nom des dimnames de ta table par exemple ou passant les noms que tu veux utiliser dans l'argument dnn.

Code : Tout sélectionner

x <- rbinom(4, 1, 0.5)
y <- rbinom(4, 1, 0.5)
bob <- table(x, row.names = y)
bob
   row.names
x   0 1
  0 1 0
  1 2 1
dimnames(bob)
$`x`
[1] "1" "2" "3" "4"

$row.names
[1] "1" "2"
names(dimnames(bob)) <- c("x", "y")
bob
   y
x   0 1
  0 1 0
  1 2 1
# ou
table(x, row.names = y, dnn = c("x", "y"))
   y
x   0 1
  0 1 0
  1 2 1
Cordialement,
Maxime

Eric Wajnberg
Messages : 776
Enregistré le : 11 Aoû 2008, 15:37
Contact :

Re: table() avec argument row.names

Messagepar Eric Wajnberg » 13 Sep 2018, 13:16

Ok pour la réponse 2, merci.

Pour la réponse 1, je dois être obtus, mais je continue à ne pas comprendre. Ce que tu expliques est clair et je l'avais bien compris. Mais je continue à ne pas comprendre pourquoi cet argument est utilisé par table() pour changer les nom des lignes (c'est que je veux dire par "fonctionnellement"). Où est-il écrit dans la récupération des arguments dans le ... que l'argument numéro deux à pour objet de récupérer les noms des lignes ? C'est ceci que je continue à ne pas comprendre.

Mais bon, on va pas passer des heures là-dessus non plus.

Encore merci, Eric.

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: table() avec argument row.names

Messagepar Logez Maxime » 13 Sep 2018, 13:25

C'est peut-être moi qui ne comprend pas. L'argument deux ne sert pas à récupérer le nom des lignes, c'est l'argument dnn de la fonction table qui permet de spécifier comment seront gérer les noms. Par défaut c'est la fonction list.names(...) qui est passé à cet argument. Donc par défaut les noms sont récupérés à l'aide de cette fonction qui est interne à la fonction table. Cette fonction récupère les noms de deux manières. Soit l'objet de la liste créée par list(...) n'a pas de nom et ça sera le nom de l'objet qui sera attribué (typiquement table(x)) ou alors l'objet à un nom et c'est celui ci qui est utilisé (typiquement table(row.names = y)). Voir mon exemple précédent avec la fonction f1.

Cordialement,
Maxime

Eric Wajnberg
Messages : 776
Enregistré le : 11 Aoû 2008, 15:37
Contact :

Re: table() avec argument row.names

Messagepar Eric Wajnberg » 13 Sep 2018, 13:32

Je crois que je comprends. C'est dnn qui fait le lien.

Bon, on arrête la discussion ici. Merci encore pour l'aide !

Cordialement, Eric.


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité