stats134711
stats134711

Reputation: 636

Split a vector based on another partition

Suppose I have a partition defined by

#Partition elements of vec into adjacent chunks of size 2
vec = seq(10)
partition = split(vec,(seq_along(vec)-1) %/% 2)

$`0`
[1] 1 2

$`1`
[1] 3 4

$`2`
[1] 5 6

$`3`
[1] 7 8

$`4`
[1]  9 10

Now suppose that I have two (or more) additional vectors

vec2 = c(1,2,3,5,6,7,9,10)
vec3 = c(1,2,3,6,7,8,9,11,12)

For vec2 and vec3 how can I partition it such that it mimics the natural partition of vec and disregards either singletons or values not in vec?

For vec2:

$`0`
[1] 1 2

$`1`
[1] 3 

$`2`
[1] 5 6

$`3`
[1] 7 

$`4`
[1]  9 10

And similarly for vec3:

$`0`
[1] 1 2

$`1`
[1] 3 

$`2`
[1] 6

$`3`
[1] 7 8

$`4`
[1]  9 

$`5`
[1]  11

$`6`
[1]  12

Upvotes: 1

Views: 90

Answers (3)

Patrick Roocks
Patrick Roocks

Reputation: 3259

It's more or less the same idea as akrun had, but a bit shorter:

apply_partition <- function(vec, partition) {
  c(lapply(partition, intersect, x = vec),     # Elements contained in the partition
    as.list(setdiff(vec, unlist(partition))))  # Singletons which are not in the partition
}

Examples:

> apply_partition(vec2, partition)
$`0`
[1] 1 2

$`1`
[1] 3

$`2`
[1] 5 6

$`3`
[1] 7

$`4`
[1]  9 10

> apply_partition(vec3, partition)
$`0`
[1] 1 2

$`1`
[1] 3

$`2`
[1] 6

$`3`
[1] 7 8

$`4`
[1] 9

[[6]]
[1] 11

[[7]]
[1] 12

The list item names for the singletons are different, but if this matters, I think you can easily modify this.

Upvotes: 1

akrun
akrun

Reputation: 887971

We can loop through the partition

lapply(partition, function(x) vec2[vec2 %in% x])

and for 'vec3'

lst <- lapply(partition, function(x) vec3[vec3 %in% x])
 c(lst, as.list(vec3[!vec3 %in% unlist(lst)]))

This can be convertedd to a function

splitFun <- function(vecN, partitionlist) {
   lst <- lapply(partitionList, function(x) vecN[vecN %in% x])
   c(lst, as.list(vecN[!vecN %in% unlist(lst)]))
 }

Upvotes: 1

ssokolen
ssokolen

Reputation: 478

When using split, you are creating a vector of groups from the elements in vec; it's possible to modify those groups for vec2 and vec3.

vec = seq(10)
vec2 = c(1,2,3,5,6,7,9,10)
vec3 = c(1,2,3,6,7,8,9,11,12)

groups <- (seq_along(vec)-1) %/% 2
split(vec, groups)
split(vec2, groups[match(vec2, vec)])
split(vec3, groups[match(vec3, vec)])

For vec3 the pattern is a bit unclear... you mention that you wish to exclude values not in vec, but your example seems to run contrary to that. The above code will exclude values not in vec, but groups can be modified based on how you want to treat elements that are not in vec.

Upvotes: 0

Related Questions