Mikołaj
Mikołaj

Reputation: 385

R: subset of character vector

I want to get a subset from a character vector. However I want to obtain vector2 containing elements from initial vector between specific elements.

vector <- c("a", "", "b", "c","","d", "e")
vector

how to grab all elements between elements "b" and "e" and get vector2?

#Expected result:
vector2
"c","","d"

Upvotes: 4

Views: 4002

Answers (4)

tmfmnk
tmfmnk

Reputation: 39858

You can also try:

vector[cumsum(vector %in% c("b", "e")) == 1][-1]

[1] "c" ""  "d"

Upvotes: 0

utubun
utubun

Reputation: 4520

With negative subscripts:

x[-c(1:which(x == 'b'), which(x =='e'):length(x))]
#[1] "c" ""  "d"

In case when e is found before b it returns empty vector:

(y <- rev(x))
#[1] "e" "d" ""  "c" "b" ""  "a"
y[-c(1:which(y == 'b'), which(y =='e'):length(y))]
#character(0)

Upvotes: 0

markus
markus

Reputation: 26343

Here is one option

f <- function(x, left, right) {
  idx <- x %in% c(left, right)
  x[as.logical(cumsum(idx) * !idx)]
}

f(vector, "b", "e")
# [1] "c" ""  "d"

The first step is to calculate idx as

vector %in% c("b", "e")
# [1] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE

then calculate the cumulative sum

cumsum(vector %in% c("b", "e"))
# [1] 0 0 1 1 1 1 2

multiply by !vector %in% c("b", "e") which gives

cumsum(vector %in% c("b", "e")) * !vector %in% c("b", "e")
# [1] 0 0 0 1 1 1 0

convert to this to a logical vector and use it to subset x.


For the given example another option is charmatch

x <- charmatch(c("b", "e"), vector) + c(1, -1)
vector[seq.int(x[1], x[2])]
# [1] "c" ""  "d"

Upvotes: 2

Anders Ellern Bilgrau
Anders Ellern Bilgrau

Reputation: 10223

You can also do something like this:

vector <- c("a", "", "b", "c","","d", "e")
vector[seq(which(vector=="b")+1,which(vector=="e")-1)]
#[1] "c" ""  "d"

Upvotes: 2

Related Questions