Question

Je pourrais résoudre ce en utilisant des boucles, mais je pense essayer dans des vecteurs si mon code sera plus R-esque.

J'ai une liste de noms. Le format est prénom_nom. Je veux sortir de cette liste, une liste séparée avec les seuls prénoms. Je ne peux pas sembler obtenir mon esprit autour de la façon de le faire. Voici quelques exemples 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"   

Je pourrais 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 faire cela sans boucles?

Était-ce utile?

La solution

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 « appliquer » dans la R

Autres conseils

Et une autre approche:

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

En d'autres termes, la dernière ligne extrait le premier élément de chaque composant de la liste et simplifie alors dans un vecteur.

Comment ça marche? Eh bien, vous devez réaliser une autre façon de x[1] d'écriture est "["(x, 1), à savoir qu'il existe une fonction appelée [ qui fait subsetting. L'appel sapply appels applique cette fonction une fois pour chaque élément de la liste initiale, en passant deux arguments, l'élément de liste et 1.

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

Que diriez-vous:

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 l'approche RegEx?

Qu'en est:

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

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

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

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

Conversion des listes de trames de données est la seule façon dont je peux les amener à faire ce que je veux. Je suis impatient de lire les réponses des gens qui comprennent vraiment comment gérer des listes.

Vous aviez presque. Il vraiment est juste une question de

  1. en utilisant l'une des fonctions de *apply à boucle sur votre liste existante, je commence souvent avec lapply et parfois passe à sapply
  2. ajouter une fonction anonyme qui fonctionne sur l'un des éléments de la liste à un moment
  3. vous le saviez déjà il était strsplit(string, splitterm) et que vous avez besoin de [[1]][1] étrange pour enlever le premier terme de la réponse
  4. il suffit de mettre tous ensemble, à commencer par une namne variables préférée (comme nous rester à l'écart de t ou c et amis)

qui donne

> tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan") 
> fnames <- sapply(tlist, function(x) strsplit(x, "_")[[1]][1]) 
> fnames 
  bob_smith    mary_jane   jose_chung michael_marx charlie_ivan   
      "bob"       "mary"       "jose"    "michael"    "charlie" 
>

Vous pouvez utiliser unlist():

> tsplit <- unlist(strsplit(t,"_"))
> tsplit
 [1] "bob"     "smith"   "mary"    "jane"    "jose"    "chung"   "michael"
 [8] "marx"    "charlie" "ivan"   
> t_out <- tsplit[seq(1, length(tsplit), by = 2)]
> t_out
[1] "bob"     "mary"    "jose"    "michael" "charlie"

Il pourrait y avoir une meilleure façon de retirer uniquement les entrées indexées impaires, mais dans tous les cas, vous n'aurez pas une boucle.

Et une autre approche, basée sur unlist exemple de brentonk ...

tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
tsplit <- unlist(strsplit(tlist,"_"))
fnames <- tsplit[seq(1:length(tsplit))%%2 == 1]

J'utiliser le unlist () suivant - méthode basée sur:

> t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
> tsplit <- strsplit(t,"_")
> 
> x <- matrix(unlist(tsplit), 2)
> x[1,]
[1] "bob"     "mary"    "jose"    "michael" "charlie"

Le grand avantage de cette méthode est qu'elle permet de résoudre le problème équivalent des noms en même temps:

> x[2,]
[1] "smith" "jane"  "chung" "marx"  "ivan" 

L'inconvénient est que vous devez être certain que tous les noms conformes à la structure firstname_lastname; le cas échéant ne puis pas cette méthode va se rompre.

de l'objet de liste tsplit originale donnée au début, cette commande fera:

unlist(lapply(tsplit,function(x) x[1]))

il extrait le premier élément de tous les éléments de la liste, une liste transforme ensuite en un vecteur. D'abord à une non-inscription matrice, puis extraire la colonne de poing est ok, mais alors vous dépendent du fait que tous les éléments de la liste ont la même longueur. Voici la sortie:

> tsplit

[[1]]
[1] "bob"   "smith"

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

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

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

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

> lapply(tsplit,function(x) x[1])

[[1]]
[1] "bob"

[[2]]
[1] "mary"

[[3]]
[1] "jose"

[[4]]
[1] "michael"

[[5]]
[1] "charlie"

> unlist(lapply(tsplit,function(x) x[1]))

[1] "bob"     "mary"    "jose"    "michael" "charlie"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top