Разделять вектор на R каждый раз, когда изменяется элемент вектора - PullRequest
1 голос
/ 10 марта 2020

Мне нужно разделить вектор повторяющихся групп элементов каждый раз, когда изменяется значение элемента. Например:

test_vector <- c("string1", "string1", "string1", "string2", 
  "string2", "string1", "string1", "string3")

должно стать:

$`1`
[1] "string1" "string1" "string1"

$`2`
[1] "string2" "string2"

$`3`
[1] "string1" "string1"

$`4`
[1] "string3"

Если я попытаюсь split(test_vector, test_vector) Я получу неправильный вывод:

$string1
[1] "string1" "string1" "string1" "string1" "string1"

$string2
[1] "string2" "string2"

$string3
[1] "string3"

Я написал код, который достигает этого, но это кажется излишне долгим, и я чувствую, что упускаю что-то гораздо более простое:

# find indices where splitting will occur:
split_points <- rep(F, length(test_vector))
for (i in 1:length(test_vector)) {
  if (i != 1) {
    if (test_vector[i] != test_vector[i-1]) {
      split_points[i] <- T
    }
  }
}
split_points <- c(1, which(split_points))

# create split vector:
split_code <- rep(1, length(test_vector))
for ( j in 1:length(split_points) ) {

  if (j!=length(split_points)) {
    split_code[
      split_points[j]:(split_points[j+1]-1)
    ] <- j
  } else {
    split_code[
      split_points[j]:length(test_vector)
    ] <- j
  }

}

split_result <- split(test_vector, split_code)
$`1`
[1] "string1" "string1" "string1"

$`2`
[1] "string2" "string2"

$`3`
[1] "string1" "string1"

$`4`
[1] "string3"

Если кто-нибудь может помочь мне найти более простое решение, это было бы очень полезно!

Ответы [ 3 ]

1 голос
/ 10 марта 2020
f = cumsum(c(TRUE, test_vector[-length(test_vector)] != test_vector[-1]))
split(test_vector, f)

ИЛИ

with(rle(test_vector), Map(rep, values, lengths))
0 голосов
/ 10 марта 2020

Базовым вариантом R является использование findInterval + cumsum + rle, т. Е.

res <- split(test_vector,
             findInterval(seq_along(test_vector),
                          cumsum(rle(test_vector)$lengths),
                          left.open = TRUE))

таким, что

> res
$`1`
[1] "string1" "string1" "string1"

$`2`
[1] "string2" "string2"

$`3`
[1] "string1" "string1"

$`4`
[1] "string3"
0 голосов
/ 10 марта 2020

В base R мы можем использовать rle для получения кодировки длины серии вектора

grp <- with(rle(test_vector), rep(seq_along(values), lengths))

Используйте это для split vector

split(test_vector, grp)

С data.table, rleid дает идентификатор на основе разницы между соседними элементами

library(data.table)
split(test_vector, rleid(test_vector))
...