2012-01-24 11 views
12

Teniendo en cuenta el siguiente vector:Extracto de vectores de la lista strsplit sin utilizar un bucle de

[1] "1-1694429" "2-1546669" "3-928598" "4-834486" "5-802353" "6-659439" "7-552850" 
"8-516804" "9-364061" 
[10] "10-354181" "11-335154" "12-257915" "13-251310" "14-232313" "15-217628" "16-216569" 

Estoy intentando generar dos vectores, cada uno de ellos que contiene los valores obtenidos dividiendo cada elemento del vector por el delimitador " - ".

utilicé:

f <- function(s) strsplit(s, "-") 
cc<-sapply(names.reads, f) 

cabeza (cc) $ 1-1694429 [1] "1" "1694429"

$`2-1546669` 

[1] "2"  "1546669" 

Sé que puedo acceder a ellos les gusta:

> cc[[1]][1] 
[1] "1" 

> cc[[1]][2] 
[1] "1694429" 

Me gustaría tener dos vectores, cada uno contiene los valores almacenados en cc[[i]][1] y cc[[i]][2] ... ¿Puedo hacer eso sin usar un bucle? (Tengo más de 1 millón de elementos)

+1

No estoy seguro de lo que quiere decir con "seleccionar por separado sin usar un bucle" - tendrá que hacer cc [[i]] para el i-ésimo vector ... ¿quiere decir que solo quiere un vector plano con todos los bits de cadena en ella? (por cierto, puedes hacer 'cc <- strsplit (names.reads, '-')' sin tener que usar 'sapply'. –

+0

@ mathematical.coffee He editado mi pregunta, espero que sea un poco más clara. – agatha

Respuesta

18

Uso de la sugerencia de mathematical.coffee, el siguiente código evita bucles o sapply

names.reads <- c("1-1694429", "2-1546669", "3-928598", "4-834486", "5-802353", 
       "6-659439", "7-552850", "8-516804", "9-364061", "10-354181", 
       "11-335154", "12-257915", "13-251310", "14-232313", "15-217628", 
       "16-216569") 

cc  <- strsplit(names.reads,'-') 
part1 <- unlist(cc)[2*(1:length(names.reads))-1] 
part2 <- unlist(cc)[2*(1:length(names.reads)) ] 

produce

> part1 
[1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15" 
[16] "16" 
> part2 
[1] "1694429" "1546669" "928598" "834486" "802353" "659439" "552850" 
[8] "516804" "364061" "354181" "335154" "257915" "251310" "232313" 
[15] "217628" "216569" 

aunque sí requiere cada valor original de estar en el formato esperado

+0

Estoy aceptando su respuesta, porque fallé falsamente en menos de un cuarto del tamaño de mi vector (siempre así con sapply por alguna razón) y su buena solución me queda mejor. – agatha

+0

Es la más rápida, pero el problema con esta solución es que todos los elementos deben tener la forma: 'x_xxxxx' una vez que tiene la misión uno del valor, no funciona bien, por ejemplo:' 1694429' en lugar de: '1-1694429'. El' strsplit 'para esos casos solo genera una lista con un valor, no con el par de valores. Luego, el cálculo de la selección del índice par e impar no funciona. La solución apuntada por @ MYaseen208 es la que tiene menos rendimiento pero cubre este caso. –

2

Buscando resolver un problema similar, se encontró con esta publicación. Agregando mi solución a esto, ¡aunque estoy muy adelante en el futuro! (Copiar de Henry el código)

names.reads <- c("1-1694429", "2-1546669", "3-928598", "4-834486", "5-802353", 
      "6-659439", "7-552850", "8-516804", "9-364061", "10-354181", 
      "11-335154", "12-257915", "13-251310", "14-232313", "15-217628", 
      "16-216569") 

require(plyr) 
cc <- ldply(strsplit(names.reads, '-')) 
cc$V1;cc$V2 

que produce una trama de datos de la cual los vectores pertenecientes al elemento n-ésimo de cada elemento de la lista pueden ser extraídos.

4

Otro enfoque:

names.reads <- c("1-1694429", "2-1546669", "3-928598", "4-834486", "5-802353", 
       "6-659439", "7-552850", "8-516804", "9-364061", "10-354181", 
       "11-335154", "12-257915", "13-251310", "14-232313", "15-217628", 
       "16-216569") 

library(reshape2) 
colsplit(string=names.reads, pattern="-", names=c("Part1", "Part2")) 

    Part1 Part2 
1  1 1694429 
2  2 1546669 
3  3 928598 
4  4 834486 
5  5 802353 
6  6 659439 
7  7 552850 
8  8 516804 
9  9 364061 
10 10 354181 
11 11 335154 
12 12 257915 
13 13 251310 
14 14 232313 
15 15 217628 
16 16 216569 
4

Usando sapply() (por completitud sake):

y <- c("1-1694429", "2-1546669", "3-928598", "4-834486", "5-802353", "6-659439", "7-552850", "8-516804", "9-364061", "10-354181", "11-335154", "12-257915", "13-251310", "14-232313", "15-217628", "16-216569")

x <- sapply(y, function(x) strsplit(x, "-")[[1]])

a <- x[1,]

b <- x[2,]

Si no desea que los nombres en el resultado, como sapply() proporciona, se puede establecer a NULL:

names(a) <- NULL

+1

esta solución lo divide dos veces. computacionalmente caro – userJT

+0

Tienes razón, gracias. Actualizado la respuesta. – pedrostrusso

3

O con el paquete de purrr:

Parte 1:

> map(strsplit(names.reads, "-"), ~.x[1]) %>% unlist() 
[1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" 
[14] "14" "15" "16" 

Parte 2:

> map(strsplit(names.reads, "-"), ~.x[2]) %>% unlist() 
[1] "1694429" "1546669" "928598" "834486" "802353" "659439" 
[7] "552850" "516804" "364061" "354181" "335154" "257915" 
[13] "251310" "232313" "217628" "216569" 
Cuestiones relacionadas