45 votes

Le style de dictionnaire remplace plusieurs éléments

J'ai un grand data.frame de données de caractères que je veux convertir en fonction de ce qu'on appelle communément un dictionnaire dans d'autres langues.

Actuellement, je m'y prends comme ceci :

 foo <- data.frame(snp1 = c("AA", "AG", "AA", "AA"), snp2 = c("AA", "AT", "AG", "AA"), snp3 = c(NA, "GG", "GG", "GC"), stringsAsFactors=FALSE)
foo <- replace(foo, foo == "AA", "0101")
foo <- replace(foo, foo == "AC", "0102")
foo <- replace(foo, foo == "AG", "0103")

Cela fonctionne bien, mais ce n'est évidemment pas joli et semble idiot de répéter l' replace chaque fois que je veux remplacer un élément dans le data.frame.

Existe-t-il une meilleure façon de procéder puisque j'ai un dictionnaire d'environ 25 paires clé/valeur ?

40voto

c.gutierrez Points 367

Si vous êtes ouvert à l'utilisation de packages, plyr est très populaire et possède cette fonction mapvalues() pratique qui fera exactement ce que vous recherchez :

 foo <- mapvalues(foo, from=c("AA", "AC", "AG"), to=c("0101", "0102", "0103"))

Notez que cela fonctionne pour les types de données de toutes sortes, pas seulement pour les chaînes.

37voto

Martin Morgan Points 19965
map = setNames(c("0101", "0102", "0103"), c("AA", "AC", "AG"))
foo[] <- map[unlist(foo)]

en supposant que map couvre tous les cas en foo . Cela ressemblerait moins à un "piratage" et serait plus efficace dans l'espace et dans le temps si foo était une matrice (de caractère()), alors

 matrix(map[foo], nrow=nrow(foo), dimnames=dimnames(foo))

Les variantes de matrice et de trame de données vont à l'encontre de la limite 2^31-1 de R sur la taille du vecteur lorsqu'il y a des millions de SNP et des milliers d'échantillons.

16voto

Ramnath Points 24798

Voici une solution rapide

 dict = list(AA = '0101', AC = '0102', AG = '0103')
foo2 = foo
for (i in 1:3){foo2 <- replace(foo2, foo2 == names(dict[i]), dict[i])}

8voto

Clément LVD Points 11

L'un des moyens les plus lisibles de remplacer une valeur dans une chaîne ou un vecteur de chaîne par un dictionnaire est stringr::str_replace_all , du package stringr Le modèle requis par str_replace_all peut être un dictionnaire, par exemple,

 # 1. Made your dictionnary
dictio_replace= c("AA"= "0101", 
                  "AC"= "0102",
                  "AG"= "0103") # short example of dictionnary.

 # 2. Replace all pattern, according to the dictionary-values (only a single vector of string, or a single string)
 foo$snp1 <- stringr::str_replace_all(string = foo$snp1,
                                      pattern= dictio_replace)  # we only use the 'pattern' option here: 'replacement' is useless since we provide a dictionnary.

Répétez l'étape 2 avec foo$snp2 & foo$snp3. Si vous avez plus de vecteurs à transformer, c'est une bonne idée d'utiliser un autre func', afin de remplacer les valeurs dans chacune des colonnes/vecteur de la trame de données sans vous répéter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X