How to insert elements into a vector?

R

R Problem Overview


I have a logical vector, for which I wish to insert new elements at particular indexes. I've come up with a clumsy solution below, but is there a neater way?

probes <- rep(TRUE, 15)
ind <- c(5, 10)
probes.2 <- logical(length(probes)+length(ind))
probes.ind <- ind + 1:length(ind)
probes.original <- (1:length(probes.2))[-probes.ind]
probes.2[probes.ind] <- FALSE
probes.2[probes.original] <- probes

print(probes)

gives

[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

and

print(probes.2)

gives

[1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
[13]  TRUE  TRUE  TRUE  TRUE  TRUE

So it works but is ugly looking - any suggestions?

R Solutions


Solution 1 - R

These are all very creative approaches. I think working with indexes is definitely the way to go (Marek's solution is very nice).

I would just mention that there is a function to do roughly that: append().

probes <- rep(TRUE, 15)
probes <- append(probes, FALSE, after=5)
probes <- append(probes, FALSE, after=11)

Or you could do this recursively with your indexes (you need to grow the "after" value on each iteration):

probes <- rep(TRUE, 15)
ind <- c(5, 10)
for(i in 0:(length(ind)-1)) 
	probes <- append(probes, FALSE, after=(ind[i+1]+i))

Incidentally, http://tolstoy.newcastle.edu.au/R/help/04/11/7695.html">this question was also previously asked on R-Help. As Barry says:

"Actually I'd say there were no ways of doing this, since I dont think you can actually insert into a vector - you have to create a new vector that produces the illusion of insertion!"

Solution 2 - R

You can do some magic with indexes:

First create vector with output values:

probs <- rep(TRUE, 15)
ind <- c(5, 10)
val <- c( probs, rep(FALSE,length(ind)) )
# > val
#  [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
# [13]  TRUE  TRUE  TRUE FALSE FALSE

Now trick. Each old element gets rank, each new element gets half-rank

id  <- c( seq_along(probs), ind+0.5 )
# > id
#  [1]  1.0  2.0  3.0  4.0  5.0  6.0  7.0  8.0  9.0 10.0 11.0 12.0 13.0 14.0 15.0
# [16]  5.5 10.5

Then use order to sort in proper order:

val[order(id)]
#  [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
# [13]  TRUE  TRUE  TRUE  TRUE  TRUE

Solution 3 - R

probes <- rep(TRUE, 1000000)
ind <- c(50:100)
val <- rep(FALSE,length(ind))

new.probes <- vector(mode="logical",length(probes)+length(val))
new.probes[-ind] <- probes
new.probes[ind] <- val

Some timings: My method user system elapsed 0.03 0.00 0.03

Marek method user system elapsed 0.18 0.00 0.18

R append with for loop user system elapsed 1.61 0.48 2.10

Solution 4 - R

How about this:

> probes <- rep(TRUE, 15)
> ind <- c(5, 10)

> probes.ind <- rep(NA, length(probes))
> probes.ind[ind] <- FALSE
> new.probes <- as.vector(rbind(probes, probes.ind))
> new.probes <- new.probes[!is.na(new.probes)]
> new.probes
 [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
[13]  TRUE  TRUE  TRUE  TRUE  TRUE

Solution 5 - R

That is sorta tricky. Here's one way. It iterates over the list, inserting each time, so it's not too efficient.

probes <- rep(TRUE, 15)
probes.ind <- ind + 0:(length(ind)-1)
for (i in probes.ind) {
  probes <- c(probes[1:i], FALSE, probes[(i+1):length(probes)])
}

> probes
 [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
[13]  TRUE  TRUE  TRUE  TRUE  TRUE

This should even work if ind has repeated elements, although ind does need to be sorted for the probes.ind construction to work.

Solution 6 - R

Or you can do it using the insertRow function from the miscTools package.

probes <- rep(TRUE, 15)
ind <- c(5,10)
for (i in ind){
    probes <- as.vector(insertRow(as.matrix(probes), i, FALSE))
}

Solution 7 - R

I came up with a good answer that's easy to understand and fairly fast to run, building off Wojciech's answer above. I'll adapt the method for the example here, but it can be easily generalized to pretty much any data type for an arbitrary pattern of missing points (shown below).

probes <- rep(TRUE, 15)
ind <- c(5,10)

probes.final <- rep(FALSE, length(probes)+length(ind))
probes.final[-ind] <- probes

The data I needed this for is sampled at a regular interval, but many samples are thrown out, and the resulting data file only includes the timestamps and measurements for those retained. I needed to produce a vector containing all the timestamps and a data vector with NAs inserted for timestamps that were tossed. I used the "not in" function stolen from here to make it a bit simpler.

`%notin%` <- Negate(`%in%`)
dat <- rnorm(50000) # Data given
times <- seq(from=554.3, by=0.1, length.out=70000] # "Original" time stamps
times <- times[-sample(2:69999, 20000)] # "Given" times with arbitrary points missing from interior

times.final <- seq(from=times[1], to=times[length(times)], by=0.1)
na.ind <- which(times.final %notin% times)
dat.final <- rep(NA, length(times.final))
dat.final[-na.ind] <- dat

Solution 8 - R

Um, hi, I had the same doubt, but I couldn't understand what people had answered, because I'm still learning the language. So I tried make my own and I suppose it works! I created a vector and I wanted to insert the value 100 after the 3rd, 5th and 6th indexes. This is what I wrote.

vector <-  c(0:9)
indexes <-  c(6, 3, 5)
indexes <- indexes[order(indexes)]
i <-  1
j <-  0

while(i <= length(indexes)){
  vector <- append(vector, 100, after = indexes[i] + j)
  i <-i + 1
  j <- j + 1
}
vector

The vector "indexes" must be in ascending order for this to work. This is why I put them in order at the third line. The variable "j" is necessary because at each iteration, the length of the new vector increases and the original values are moved. In the case you wish to insert the new value next to each other, simply repeat the number of the index. For instance, by assigning indexes <- c(3, 5, 5, 5, 6), you should get vector == 0 1 2 100 3 4 100 100 100 5 100 6 7 8 9

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAaron StathamView Question on Stackoverflow
Solution 1 - RShaneView Answer on Stackoverflow
Solution 2 - RMarekView Answer on Stackoverflow
Solution 3 - RWojciech SobalaView Answer on Stackoverflow
Solution 4 - RJonathan ChangView Answer on Stackoverflow
Solution 5 - RHarlanView Answer on Stackoverflow
Solution 6 - RunknownView Answer on Stackoverflow
Solution 7 - RBenView Answer on Stackoverflow
Solution 8 - RPauloView Answer on Stackoverflow