2012-07-23 26 views

Respuesta

38

Esta es una manera

substring("aabbccccdd", seq(1, 9, 2), seq(2, 10, 2)) 
#[1] "aa" "bb" "cc" "cc" "dd" 

o más generalmente

text <- "aabbccccdd" 
substring(text, seq(1, nchar(text)-1, 2), seq(2, nchar(text), 2)) 
#[1] "aa" "bb" "cc" "cc" "dd" 

Editar: Esto es mucho, mucho más rápido

sst <- strsplit(text, "")[[1]] 
out <- paste0(sst[c(TRUE, FALSE)], sst[c(FALSE, TRUE)]) 

En primer lugar, se divide la cadena en caracteres. Luego, pega juntos los elementos pares y los elementos impares.

sincronizaciones

text <- paste(rep(paste0(letters, letters), 1000), collapse="") 
g1 <- function(text) { 
    substring(text, seq(1, nchar(text)-1, 2), seq(2, nchar(text), 2)) 
} 
g2 <- function(text) { 
    sst <- strsplit(text, "")[[1]] 
    paste0(sst[c(TRUE, FALSE)], sst[c(FALSE, TRUE)]) 
} 
identical(g1(text), g2(text)) 
#[1] TRUE 
library(rbenchmark) 
benchmark(g1=g1(text), g2=g2(text)) 
# test replications elapsed relative user.self sys.self user.child sys.child 
#1 g1   100 95.451 79.87531 95.438  0   0   0 
#2 g2   100 1.195 1.00000  1.196  0   0   0 
+0

interesante, no sabía nada de 'substring'. Mucho más agradable ya que 'substr' no toma args vectoriales para inicio/finalización. –

+2

¡genial! la segunda versión es realmente muy rápida! – MadSeb

+0

Me preguntaba si había algo como esto que dividiría "aabbbcccccdd" en aa bbb ccccc dd Uso grepexpr por el momento. – jackStinger

8
string <- "aabbccccdd" 
# total length of string 
num.chars <- nchar(string) 

# the indices where each substr will start 
starts <- seq(1,num.chars, by=2) 

# chop it up 
sapply(starts, function(ii) { 
    substr(string, ii, ii+1) 
}) 

que da

[1] "aa" "bb" "cc" "cc" "dd" 
1

Uno puede utilizar una matriz para agrupar los personajes:

s2 <- function(x) { 
    m <- matrix(strsplit(x, '')[[1]], nrow=2) 
    apply(m, 2, paste, collapse='') 
} 

s2('aabbccddeeff') 
## [1] "aa" "bb" "cc" "dd" "ee" "ff" 

Desafortunadamente, TH es pausas para una entrada de longitud de la cadena impar, dando una advertencia:

s2('abc') 
## [1] "ab" "ca" 
## Warning message: 
## In matrix(strsplit(x, "")[[1]], nrow = 2) : 
## data length [3] is not a sub-multiple or multiple of the number of rows [2] 

Más lamentable es que g1 y g2 de @GSee silencio devolver resultados incorrectos para una entrada de longitud de la cadena impar:

g1('abc') 
## [1] "ab" 

g2('abc') 
## [1] "ab" "cb" 

Aquí está la función en el espíritu de s2, tomando un parámetro para el número de caracteres en cada grupo, y deja la última entrada corta si es necesario:

s <- function(x, n) { 
    sst <- strsplit(x, '')[[1]] 
    m <- matrix('', nrow=n, ncol=(length(sst)+n-1)%/%n) 
    m[seq_along(sst)] <- sst 
    apply(m, 2, paste, collapse='') 
} 

s('hello world', 2) 
## [1] "he" "ll" "o " "wo" "rl" "d" 
s('hello world', 3) 
## [1] "hel" "lo " "wor" "ld" 

(De hecho, es más lento que g2, pero más rápido que g1 por un factor de aproximadamente 7)

+0

Si es posible tener un número impar de caracteres, entonces me parece que sería más rápido manejar eso después del hecho que para introducir un bucle 'apply'. Apuesto a que es más rápido: 'out <- g2 (x); if (nchar (x) %% 2 == 1L) fuera [length (out)] <- substring (out [length (out)], 1, 1); fuera' – GSee

1

feo, pero funciona

sequenceString <- "ATGAATAAAG" 

J=3#maximum sequence length in file 
sequenceSmallVecStart <- 
    substring(sequenceString, seq(1, nchar(sequenceString)-J+1, J), 
    seq(J,nchar(sequenceString), J)) 
sequenceSmallVecEnd <- 
    substring(sequenceString, max(seq(J, nchar(sequenceString), J))+1) 
sequenceSmallVec <- 
    c(sequenceSmallVecStart,sequenceSmallVecEnd) 
cat(sequenceSmallVec,sep = "\n") 

Da ATG AAT AAA G

5

hay dos posibilidades fáciles:

s <- "aabbccccdd" 
  1. gregexpr y regmatches:

    regmatches(s, gregexpr(".{2}", s))[[1]] 
    # [1] "aa" "bb" "cc" "cc" "dd" 
    
  2. strsplit:

    strsplit(s, "(?<=.{2})", perl = TRUE)[[1]] 
    # [1] "aa" "bb" "cc" "cc" "dd" 
    
Cuestiones relacionadas