Daniel James
Daniel James

Reputation: 1433

Split vector to equal-overlapping sub-vector length when the sub-vector length is even or odd

Given a vector of vec <- 1:n and l to be the subvector length, I want an R function that breaks a vector into subvectors. This R function works When l is even number.

splitWithOverlap <- function(vec, seg.length, overlap) {      
  starts = seq(1, length(vec) - 1, by=seg.length-overlap)
  ends   = starts + seg.length - 1
  ends[ends > length(vec)] = length(vec)  
  lapply(1:length(starts), function(i) vec[starts[i]:ends[i]])
}
## try the function
vec <- 1:17
l <- 6
ov = ceiling(l/2)
splitWithOverlap(vec, l, ov)

The problem is when l is odd number such that the half-way can not be found. The solution to the odd number of l case can be solve by telling R to alternate between ov = ceiling(l/2) and ov = ceiling(l/2) - 1 such that I will have result like Figure 2 or Figure 4. Picture to show my desired output

Upvotes: 1

Views: 126

Answers (1)

G. Grothendieck
G. Grothendieck

Reputation: 269491

This gives the starts and ends given the len and ov (overlap) listed below each figure and n, the number of x's. In the output start[i] is the start of the ith block and end[i] is the end of the ith block.

blocks <- function(len, ov, n) {

  starts <- unique(sort(c(seq(1, n, len), seq(len-ov+1, n, len))))
  ends <- pmin(starts + len - 1, n)

  # truncate starts and ends to the first num elements
  num <- match(n, ends)
  head(data.frame(starts, ends), num)
}

Using the inputs listed below the figures in the question we can double check that it does indeed give the correct starts and ends for each block:

fig1 <- blocks(len = 2, ov = 1, n = 17)
str(fig1, vec.len = Inf)
## 'data.frame':   16 obs. of  2 variables:
##  $ starts: num  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
##  $ ends  : num  2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
      
fig2 <- blocks(len = 3, ov = 2, n = 17)
str(fig2, vec.len = Inf)
## 'data.frame':   11 obs. of  2 variables:
##  $ starts: num  1 2 4 5 7 8 10 11 13 14 16
##  $ ends  : num  3 4 6 7 9 10 12 13 15 16 17
          
fig3 <- blocks(len = 4, ov = 2, n = 17)
str(fig3, vec.len = Inf)
## 'data.frame':   8 obs. of  2 variables:
##  $ starts: num  1 3 5 7 9 11 13 15
##  $ ends  : num  4 6 8 10 12 14 16 17
      
fig4 <- blocks(len = 5, ov = 3, n = 17)
str(fig4, vec.len = Inf)
## 'data.frame':   6 obs. of  2 variables:
##  $ starts: num  1 3 6 8 11 13
##  $ ends  : num  5 7 10 12 15 17

fig5 <- blocks(len = 6, ov = 3, n = 17)
str(fig5, vec.len = Inf)
## 'data.frame':   5 obs. of  2 variables:
## $ starts: num  1 4 7 10 13
## $ ends  : num  6 9 12 15 17

Upvotes: 2

Related Questions