while tablas programacion funcion for extraer estructuras ejemplos control contador columnas list r vector strsplit

tablas - Cómo evitar un bucle en R: seleccionar elementos de una lista



tablas en r (10)

Casi lo tienes. Realmente es solo una cuestión de

  1. usando una de las *apply funciones de *apply para recorrer su lista existente, a menudo empiezo con lapply y algunas veces cambio a sapply
  2. agregar una función anónima que opera en uno de los elementos de la lista a la vez
  3. usted ya sabía que era strsplit(string, splitterm) y que necesita el impar [[1]][1] para elegir el primer término de la respuesta
  4. simplemente ponlo todo junto, comenzando con una variable preferida namne (ya que nos mantenemos alejados de tyc y amigos)

lo que da

> 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" >

Podría resolver esto usando loops, pero estoy intentando pensar en vectores para que mi código sea más R-esque.

Tengo una lista de nombres. El formato es firstname_lastname. Quiero sacar de esta lista una lista separada con solo los nombres. Parece que no puedo entender cómo hacer esto. Aquí hay algunos datos de ejemplo:

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

que se ve así:

> tsplit [[1]] [1] "bob" "smith" [[2]] [1] "mary" "jane" [[3]] [1] "jose" "chung" [[4]] [1] "michael" "marx" [[5]] [1] "charlie" "ivan"

Podría sacar lo que quiero usando circuitos como este:

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

que me daría esto:

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

Entonces, ¿cómo puedo hacer esto sin bucles?


Dudo que esta sea la solución más elegante, pero es mejor que el bucle:

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

Convertir listas en marcos de datos es la única forma en que puedo lograr que hagan lo que quiero. Estoy deseando leer las respuestas de personas que realmente entienden cómo manejar listas.


Puede usar apply (o 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"

Ver: una breve introducción a "aplicar" en R


Puede usar 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"

Puede haber una mejor manera de extraer solo las entradas de índice impar, pero en cualquier caso no tendrá un bucle.


Qué tal si:

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

para el enfoque RegEx?


Usaría el siguiente método unlist ():

> 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"

La gran ventaja de este método es que resuelve el problema equivalente para los apellidos al mismo tiempo:

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

El inconveniente es que deberá asegurarse de que todos los nombres se ajusten a la estructura firstname_lastname ; si alguno no lo hace, entonces este método se romperá.


Y otro enfoque, basado en el ejemplo de una lista 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]


Y un enfoque más:

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

En palabras, la última línea extrae el primer elemento de cada componente de la lista y luego lo simplifica en un vector.

¿Como funciona esto? Bueno, debe darse cuenta de que una forma alternativa de escribir x[1] es "["(x, 1) , es decir, hay una función llamada [ que hace subconjuntos. La llamada sapply aplica llamadas a esta función una vez para cada elemento de la lista original, pasando dos argumentos, el elemento de lista y 1.

La ventaja de este enfoque sobre los demás es que puede extraer múltiples elementos de la lista sin tener que volver a calcular los splits. Por ejemplo, el apellido sería sapply(pieces, "[", 2) . Una vez que te acostumbras a este idioma, es bastante fácil de leer.


del objeto de la lista tsplit original dado al comienzo, este comando hará:

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

extrae el primer elemento de todos los elementos de la lista, luego transforma una lista en un vector. Deslisar primero en una matriz, luego extraer la primera columna también está bien, pero luego depende del hecho de que todos los elementos de la lista tengan la misma longitud. Aquí está el resultado:

> 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"


qué pasa:

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan") sub("_.*", "", t)