vectores tamaño seleccionar eliminar elementos data contar concatenar columnas r

seleccionar - tamaño de un vector en r



Insertar elementos en un vector en R (6)

Aquí hay otra función, usando la sintaxis de Ricardo, la división de Ferdinand y el truco de intercalado de @ Arun de otra pregunta:

ins2 <- function(a,bs,pos){ as <- split(a,cumsum(seq(a)%in%(pos+1))) idx <- order(c(seq_along(as),seq_along(bs))) unlist(c(as,bs)[idx]) }

La ventaja es que esto debería extenderse a más inserciones. Sin embargo, puede producir resultados extraños cuando se pasan argumentos no válidos, por ejemplo, con any(pos > length(a)) o length(bs)!=length(pos) .

Puede cambiar la última línea a unname(unlist(... si no desea que se unname(unlist(... los elementos de a.

Tengo un vector en R,

a = c(2,3,4,9,10,2,4,19)

Digamos que quiero insertar de manera eficiente los siguientes vectores, b y c,

b = c(2,1) d = c(0,1)

en las posiciones 3 y 7, resultando en,

e = c(2,3,4,2,1,9,10,2,4,0,1,19)

¿Cómo haría esto de manera eficiente en R, sin usar cbind o menos recursivamente cbind

Encontré un paquete R.basic pero no es parte de los paquetes CRAN, así que pensé en usar una versión compatible.


Aquí hay una alternativa que usa append . Está bien para vectores pequeños, pero no puedo imaginar que sea eficiente para vectores grandes ya que se crea un nuevo vector en cada iteración del bucle (lo cual es, obviamente, malo). El truco es revertir el vector de cosas que se deben insertar para append en el lugar correcto en relación con el vector original.

a = c(2,3,4,9,10,2,4,19) b = c(2,1) d = c(0,1) pos <- c(3, 7) z <- setNames(list(b, d), pos) z <- z[order(names(z), decreasing=TRUE)] for (i in seq_along(z)) { a <- append(a, z[[i]], after = as.numeric(names(z)[[i]])) } a # [1] 2 3 4 2 1 9 10 2 4 0 1 19


Después de usar la función de Ferdinand, intenté escribir la mía y, sorprendentemente, es mucho más eficiente.
Aquí está el mío :

insertElems = function(vect, pos, elems) { l = length(vect) j = 0 for (i in 1:length(pos)){ if (pos[i]==1) vect = c(elems[j+1], vect) else if (pos[i] == length(vect)+1) vect = c(vect, elems[j+1]) else vect = c(vect[1:(pos[i]-1+j)], elems[j+1], vect[(pos[i]+j):(l+j)]) j = j+1 } return(vect) } tmp = c(seq(1:5)) insertElems(tmp, c(2,4,5), c(NA,NA,NA)) # [1] 1 NA 2 3 NA 4 NA 5 insert.at(tmp, c(2,4,5), c(NA,NA,NA)) # [1] 1 NA 2 3 NA 4 NA 5

Y ahí está el resultado de referencia:

> microbenchmark(insertElems(tmp, c(2,4,5), c(NA,NA,NA)), insert.at(tmp, c(2,4,5), c(NA,NA,NA)), times = 10000) Unit: microseconds expr min lq mean median uq max neval insertElems(tmp, c(2, 4, 5), c(NA, NA, NA)) 9.660 11.472 13.44247 12.68 13.585 1630.421 10000 insert.at(tmp, c(2, 4, 5), c(NA, NA, NA)) 58.866 62.791 70.36281 64.30 67.923 2475.366 10000

Mi código funciona incluso mejor en algunos casos:

> insert.at(tmp, c(1,4,5), c(NA,NA,NA)) # [1] 1 2 3 NA 4 NA 5 NA 1 2 3 # Warning message: # In result[c(TRUE, FALSE)] <- split(a, cumsum(seq_along(a) %in% (pos))) : # number of items to replace is not a multiple of replacement length > insertElems(tmp, c(1,4,5), c(NA,NA,NA)) # [1] NA 1 2 3 NA 4 NA 5


El enfoque directo:

b.pos <- 3 d.pos <- 7 c(a[1:b.pos],b,a[(b.pos+1):d.pos],d,a[(d.pos+1):length(a)]) [1] 2 3 4 2 1 9 10 2 4 0 1 19

Tenga en cuenta la importancia del paréntesis para los límites del operador : .


Prueba esto:

result <- vector("list",5) result[c(TRUE,FALSE)] <- split(a, cumsum(seq_along(a) %in% (c(3,7)+1))) result[c(FALSE,TRUE)] <- list(b,d) f <- unlist(result) identical(f, e) #[1] TRUE

EDITAR: la generalización a un número arbitrario de inserciones es directa:

insert.at <- function(a, pos, ...){ dots <- list(...) stopifnot(length(dots)==length(pos)) result <- vector("list",2*length(pos)+1) result[c(TRUE,FALSE)] <- split(a, cumsum(seq_along(a) %in% (pos+1))) result[c(FALSE,TRUE)] <- dots unlist(result) } > insert.at(a, c(3,7), b, d) [1] 2 3 4 2 1 9 10 2 4 0 1 19 > insert.at(1:10, c(4,7,9), 11, 12, 13) [1] 1 2 3 4 11 5 6 7 12 8 9 13 10 > insert.at(1:10, c(4,7,9), 11, 12) Error: length(dots) == length(pos) is not TRUE

Tenga en cuenta la comprobación de errores de bonificación si el número de posiciones e inserciones no coinciden.


Puedes usar la siguiente función,

ins(a, list(b, d), pos=c(3, 7)) # [1] 2 3 4 2 1 9 10 2 4 0 1 4 19

dónde:

ins <- function(a, to.insert=list(), pos=c()) { c(a[seq(pos[1])], to.insert[[1]], a[seq(pos[1]+1, pos[2])], to.insert[[2]], a[seq(pos[2], length(a))] ) }