Home > Software design >  R Split a Vector to Overlapping Sub-Vectors and Conjoin the First and the Last Elements
R Split a Vector to Overlapping Sub-Vectors and Conjoin the First and the Last Elements

Time:09-29

I want to split a vector to follow these three(3) conditions using R:

  1. Have an equal length of l
  2. Overlap with a constant value ov
  3. The first element and the last element alone of the parent vector should be for the last chunk (with just the two elements).

I got the below R code to meet the first two conditions as follows

ts = 1:10
l = 7
ov = l -1

library(tidyverse)
anil <- function(ts, l, ov){
  seq_len((length(ts) - ov) %/% (l - ov)  1) %>%
    as.data.frame() %>%
    setNames('id') %>%
    mutate(start = accumulate(id, ~ .x   l - ov),
           end = pmin(start   l - 1, length(ts)),
           start = pmin(start, end - l   1)) %>%
    filter(!duplicated(paste(start, end, sep = '-'))) %>%
    transmute(desired = map2(start, end, ~ ts[.x:.y])) %>%
    as.list
}

anil(ts, l, ov)

I got this result:

>$desired[[1]]
[1] 1 2 3 4 5 6 7

>$desired[[2]]
[1] 2 3 4 5 6 7 8

>$desired[[3]]
[1] 3 4 5 6 7 8 9

>$desired[[4]]
[1]  4  5  6  7  8  9 10

I need help to meet the `third condition.

I want my result to look like this:

>$desired[[1]]
[1] 1 2 3 4 5 6 7

>$desired[[2]]
[1] 2 3 4 5 6 7 8

>$desired[[3]]
[1] 3 4 5 6 7 8 9

>$desired[[4]]
[1]  4  5  6  7  8  9 10

>$desired[[5]]
[1]  1  10

CodePudding user response:

Maybe we can use the following code with embed asplit range

c(
  asplit(embed(ts, l)[seq(1, length(ts) - l   1, l - ov), l:1], 1),
  list(range(ts))
)

which gives

[[1]]
[1] 1 2 3 4 5 6 7

[[2]]
[1] 2 3 4 5 6 7 8

[[3]]
[1] 3 4 5 6 7 8 9

[[4]]
[1]  4  5  6  7  8  9 10

[[5]]
[1]  1 10

CodePudding user response:

Append with the range of 'ts' in summarise before the as.list

anil <- function(ts, l, ov){
  seq_len((length(ts) - ov) %/% (l - ov)  1) %>%
    as.data.frame() %>%
    setNames('id') %>%
    mutate(start = accumulate(id, ~ .x   l - ov),
           end = pmin(start   l - 1, length(ts)),
           start = pmin(start, end - l   1)) %>%
    filter(!duplicated(paste(start, end, sep = '-'))) %>%
    transmute(desired = map2(start, end, ~ ts[.x:.y])) %>%
    summarise(desired = c(desired, list(range(ts)))) %>%
    as.list
    
}

-testing

anil(ts, l, ov)
$desired
$desired[[1]]
[1] 1 2 3 4 5 6 7

$desired[[2]]
[1] 2 3 4 5 6 7 8

$desired[[3]]
[1] 3 4 5 6 7 8 9

$desired[[4]]
[1]  4  5  6  7  8  9 10

$desired[[5]]
[1]  1 10
  • Related