R对连续重复的奇数列表求和,并除去除第一个列表外的所有列表

时间:2019-04-08 10:37:21

标签: r

我陷入疑问。如何加入连续的重复奇数列表并删除除第一个列表以外的所有列表。 我已经知道如何对连续重复的行求和并删除除第一行以外的所有行(链接:R sum consecutive duplicate odd rows and remove all but first)。 但是这个项目,我想加入连续重复的奇数列表,但不是所有连续重复的列表。

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 个答案:

答案 0 :(得分:1)

此“几乎”仅使用基数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

答案 1 :(得分:1)

要获取所需的结构,可以使用以下基本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

答案 2 :(得分:0)

此外,以下循环方法也可以产生预期的结果:

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