R сумма последовательных дубликатов нечетного списка и удаление всех, кроме первого списка - PullRequest
3 голосов
/ 08 апреля 2019

Я застрял с вопросом. как соединить последовательный дубликат нечетного списка и удалить все, кроме первого списка. Я получил, как суммировать последовательные дубликаты строк и удалить все, кроме первой строки (ссылка: R сумма последовательных дубликатов нечетных строк и удалить все, кроме первой ). Но в этом проекте я хотел бы присоединиться к последовательному дубликату нечетного списка, но не ко всем последовательным дубликатам списка.

data.table или dplyr будет в порядке

например:

ia<-c(1,1,2,2,1,1,1,1)
time <- list(c(23,43),
             c(24,54,32), 
             c(23,43,232), 
             c(24,54,32),
             c(23,43,2), 
             c(24,54,32),
             c(24,54,32),
             c(24,54,32)
            )

до

res_time <- list(c(23,43,24,54,32), # 1+1
                 c(23,43,232),      # 2
                 c(24,54,32),       # 2
                 c(23,43,2,24,54,32,24,54,32,24,54,32) # 1+1+1+1
                 )

Спасибо!

Ответы [ 3 ]

1 голос
/ 08 апреля 2019

Чтобы получить желаемую структуру, вы можете использовать следующие базовые R функции:

## use run lengths encoding to get consecutive blocks
rl <- rle(ia)$lengths
## which of these blocks appear on an odd position
is_odd <- seq_along(rl) %% 2 == 1
## which is the last index of the consecutive blocks
ends <- cumsum(rl)
## helper function: if odd combine, otherwise leave as is
combine_or_leave <- function(in_vec, is_odd) {
   if(is_odd) {
      list(unlist(in_vec))
   } else {
      in_vec
   }
}

## apply over length, indices and is_odd flags
res <- unlist(mapply(function(lens, ends, is_odd) {
    ind <- rev(seq(ends, by = -1, length.out = lens))
    combine_or_leave(time[ind], is_odd)
}, rl, ends, is_odd), recursive = FALSE)

all.equal(res, res_time)
# [1] TRUE
res

# [[1]]
# [1] 23 43 24 54 32

# [[2]]
# [1]  23  43 232

# [[3]]
# [1] 24 54 32

# [[4]]
#  [1] 23 43  2 24 54 32 24 54 32 24 54 32
1 голос
/ 08 апреля 2019

Это "почти" дает ожидаемый результат, используя только базу R. Мы создаем последовательность группировки, используя diff. Чтобы выбрать группы поочередно, мы создаем последовательность альтернативного значения TRUE / FALSE рекурсивно, и на основе этого значения мы unlist и объединяем значения списка в mapply.

pat <- cumsum(c(0, diff(ia)) != 0)

mapply(function(x, y) if(y) unlist(time[x]) else time[x], 
 split(seq_along(time), pat), rep(c(TRUE, FALSE), length.out = length(unique(pat))))


#$`0`
#[1] 23 43 24 54 32

#$`1`
#$`1`[[1]]
#[1]  23  43 232

#$`1`[[2]]
#[1] 24 54 32


#$`2`
# [1] 23 43  2 24 54 32 24 54 32 24 54 32
0 голосов
/ 08 апреля 2019

Также следующий подход цикла дает желаемый результат:

result <- {
  splitTime <- split(time, with(rle(ia), rep(seq_along(values), lengths)))
  result <- list()
  for(i in seq_along(splitTime)) {
    if(as.integer(names(splitTime)[i]) %% 2 == 0) { 
      result <- c(result, splitTime[[i]]) } else {
        result <- c(result, list(unlist(splitTime[[i]])))
      }
  }
  result
}
print(result)
#[[1]]
#[1] 23 43 24 54 32
#
#[[2]]
#[1]  23  43 232
#
#[[3]]
#[1] 24 54 32
#
#[[4]]
#[1] 23 43  2 24 54 32 24 54 32 24 54 32
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...