web-dev-qa-db-fra.com

Travailler avec des dictionnaires / des listes dans R

J'ai une question triviale: je ne pouvais pas trouver de structure de données de dictionnaire dans R, j'ai donc utilisé la liste (comme "Word" -> numéro). Quelqu'un sait?

77
Ivri

Oui, le type list est une bonne approximation. Vous pouvez utiliser names() sur votre liste pour définir et récupérer les "clés":

> foo <- vector(mode="list", length=3)
> names(foo) <- c("tic", "tac", "toe")
> foo[[1]] <- 12; foo[[2]] <- 22; foo[[3]] <- 33
> foo
$tic
[1] 12

$tac
[1] 22

$toe
[1] 33

> names(foo)
[1] "tic" "tac" "toe"
> 
105

Vous n'avez même pas besoin de listes si vos valeurs "nombre" sont toutes du même mode. Si je prends l'exemple de Dirk Eddelbuettel:

> foo <- c(12, 22, 33)
> names(foo) <- c("tic", "tac", "toe")
> foo
tic tac toe
 12  22  33
> names(foo)
[1] "tic" "tac" "toe"

Les listes ne sont requises que si vos valeurs sont en mode mixte (par exemple, des caractères et des nombres) ou des vecteurs.

Pour les listes et les vecteurs, un élément individuel peut être sous-configuré par nom:

> foo["tac"]
tac 
 22 

Ou pour une liste:

> foo[["tac"]]
[1] 22
49
Calimo

Pour prolonger un peu la réponse de Calimo, je présente quelques éléments supplémentaires qui pourraient vous être utiles lors de la création de ce quasi-dictionnaire dans R:

a) comment renvoyer toutes les VALEURS du dictionnaire:

>as.numeric(foo)
[1] 12 22 33

b) vérifier si le dictionnaire CONTIENT LA CLÉ:

>'tic' %in% names(foo)
[1] TRUE

c) comment ajouter une nouvelle clé, valeur paire au dictionnaire:

c(foo,tic2=44)

résultats:

tic       tac       toe     tic2
12        22        33        44 

d) comment remplir l'exigence de VRAI DICTIONNAIRE - que les clés NE PEUVENT PAS se répéter (TOUCHES UNIQUES)? Vous devez combiner b) et c) et créer une fonction qui valide l’utilisation de cette clé et fait ce que vous voulez: par exemple, ne pas autoriser l’insertion, mettre à jour la valeur si la nouvelle diffère de l’ancienne, ou reconstruire d’une manière ou d’une autre la clé (par exemple: ajoute un certain nombre pour qu'il soit unique)

e) comment supprimer paire par clé du dictionnaire:

foo <-foo [qui (foo! = foo [["tac"]])]

15
andilabs

La performance des dictionnaires repose avant tout sur les performances. Bien qu'il soit exact que vous puissiez utiliser des vecteurs et des listes nommés pour cette tâche, le problème est qu'ils deviennent très lents et que vous avez besoin de plus de données en mémoire.

Pourtant, beaucoup de gens ne savent pas que R a en effet une structure de données de dictionnaire intégrée: environnements avec l'option hash = TRUE

Voir l'exemple suivant pour savoir comment le faire fonctionner:

# vectorize assign, get and exists for convenience
assign_hash <- Vectorize(assign, vectorize.args = c("x", "value"))
get_hash <- Vectorize(get, vectorize.args = "x")
exists_hash <- Vectorize(exists, vectorize.args = "x")

# keys and values
key<- c("tic", "tac", "toe")
value <- c(1, 22, 333)

# initialize hash
hash = new.env(hash = TRUE, parent = emptyenv(), size = 100L)
# assign values to keys
assign_hash(key, value, hash)
## tic tac toe 
##   1  22 333
# get values for keys
get_hash(c("toe", "tic"), hash)
## toe tic 
## 333   1
# alternatively:
mget(c("toe", "tic"), hash)
## $toe
## [1] 333
## 
## $tic
## [1] 1
# show all keys
ls(hash)
## [1] "tac" "tic" "toe"
# show all keys with values
get_hash(ls(hash), hash)
## tac tic toe 
##  22   1 333
# remove key-value pairs
rm(list = c("toe", "tic"), envir = hash)
get_hash(ls(hash), hash)
## tac 
##  22
# check if keys are in hash
exists_hash(c("tac", "nothere"), hash)
##     tac nothere 
##    TRUE   FALSE
# for single keys this is also possible:
# show value for single key
hash[["tac"]]
## [1] 22
# create new key-value pair
hash[["test"]] <- 1234
get_hash(ls(hash), hash)
##  tac test 
##   22 1234
# update single value
hash[["test"]] <- 54321
get_hash(ls(hash), hash)
##   tac  test 
##    22 54321

Edit : Sur la base de cette réponse, j'ai écrit un billet de blog avec un contexte plus détaillé: http://blog.ephorie.de/ hash-moi-si-tu-peux

13
vonjd

Le paquet hash est maintenant disponible: https://cran.r-project.org/web/packages/hash/hash.pdf

Exemples

h <- hash( keys=letters, values=1:26 )
h <- hash( letters, 1:26 )
h$a
# [1] 1
h$foo <- "bar"
h[ "foo" ]
# <hash> containing 1 key-value pair(s).
#   foo : bar
h[[ "foo" ]]
# [1] "bar"
7
Ngọc Linh Vũ

Vous voudrez peut-être regarder le hashpackage sur CRAN.

Variation plus courte de la réponse de Dirk:

# Create a Color Palette Dictionary 
> color <- c('navy.blue', 'gold', 'dark.gray')
> hex <- c('#336A91', '#F3C117', '#7F7F7F')

> # Create List
> color_palette <- as.list(hex)
> # Name List Items
> names(color_palette) <- color
> 
> color_palette
$navy.blue
[1] "#336A91"

$gold
[1] "#F3C117"

$dark.gray
[1] "#7F7F7F"
5
Nettle

Je dirai simplement que vous pouvez faire beaucoup de kilométrage avec table lorsque vous essayez de "simuler" un dictionnaire également, par exemple.

> x <- c("a","a","b","b","b","c")
> (t <- table(x))
x
a b c 
2 3 1 
> names(t)
[1] "a" "b" "c"
> o <- order(as.numeric(t))
> names(t[o])
[1] "c" "a" "b"

etc.

4
Gabriel Perdue