27 votes

Comment éviter une boucle dans R: la sélection des éléments d'une liste

Je pourrais résoudre ce à l'aide de boucles, mais je suis en train de penser dans des vecteurs, donc mon code sera plus R-esque.

J'ai une liste de noms. Le format est firstname_lastname. Je veux sortir de cette liste une liste séparée avec seulement les noms de la première. Je n'arrive pas à obtenir mon esprit autour de la façon de faire. Voici quelques exemple de données:

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
tsplit <- strsplit(t,"_")

qui ressemble à ceci:

> tsplit
[[1]]
[1] "bob"   "smith"

[[2]]
[1] "mary" "jane"

[[3]]
[1] "jose"  "chung"

[[4]]
[1] "michael" "marx"   

[[5]]
[1] "charlie" "ivan"

J'ai pu obtenir ce que je veux à l'aide de boucles comme ceci:

for (i in 1:length(tsplit)){
    if (i==1) {t_out <- tsplit[[i]][1]} else{t_out <- append(t_out, tsplit[[i]][1])} 
}

qui me donnerait ceci:

t_out
[1] "bob"     "mary"    "jose"    "michael" "charlie"

Alors, comment puis-je le faire sans les boucles?

41voto

hadley Points 33766

Et encore une approche:

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
pieces <- strsplit(t,"_")
sapply(pieces, "[", 1)

Dans les mots, la dernière ligne des extraits du premier élément de chaque élément de la liste et simplifie ensuite dans un vecteur.

Comment cela fonctionne? Eh bien, vous avez besoin de réaliser une autre façon d'écrire x[1] est "["(x, 1), c'est à dire il y a une fonction appelée [ qui ne subsetting. L' sapply appel des appels cette fonction une fois pour chaque élément de la liste originale, en passant dans deux arguments, l'élément de la liste et de 1.

L'avantage de cette approche sur les autres, c'est que vous pouvez extraire plusieurs éléments de la liste sans avoir à recalculer les divise. Par exemple, le nom de famille serait en sapply(pieces, "[", 2). Une fois que vous vous habituez à cet idiome, c'est assez facile à lire.

24voto

liebke Points 286

Vous pouvez utiliser apply (ou sapply)

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
f <- function(s) strsplit(s, "_")[[1]][1]
sapply(t, f)

bob_smith    mary_jane   jose_chung michael_marx charlie_ivan 

       "bob"       "mary"       "jose"    "michael"    "charlie" 

Voir: Une brève introduction à la "appliquer" dans la R

9voto

William Doane Points 690

Comment à ce sujet:

tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
fnames <- gsub("(_.*)$", "", tlist)
# _.* matches the underscore followed by a string of characters
# the $ anchors the search at the end of the input string
# so, underscore followed by a string of characters followed by the end of the input string

pour les RegEx approche?

9voto

Karsten Points 81

ce sujet:

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")

sub("_.*", "", t)

7voto

Matt Parker Points 7373

Je doute que cela soit la solution la plus élégante, mais il bat en boucle:

t.df <- data.frame(tsplit)
t.df[1, ]

La conversion de listes des trames de données est la seule façon je peux les amener à faire ce que je veux. Je suis impatient de lire les réponses des gens qui ont réellement comprendre comment manipuler les listes.

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