R语言 识别-1s和1 s向量内的峰

ndh0cuux  于 2023-11-14  发布在  其他
关注(0)|答案(5)|浏览(136)

我有一个向量,它看起来像这样
我需要得到1和-1的组,即
1, -11, 1, -1, -1, -11, -1
最终目的是得到这些组的起始位置和结束位置,即,
起始位置:1, 3, 8和结束位置:3, 8, 10
rle()不太符合我的要求

r <- rle(c(1, -1, 1, 1, -1, -1, -1, 1, -1))
which(rep(x = diff(sign(diff(c(-Inf, r$values, -Inf)))) == -2, times = r$lengths))
# [1] 1 3 4 8

字符串
所以在这里,我不想要4
我举的例子中的向量可能并不能覆盖所有的基,这是完全合理的,我在向量中也有0 s,这永远不会与-11相交,例如。
0 0 1 -1 1 1 -1 -1 -1 1 -1

1 -1 1 1 -1 -1 -1 1 -1 0 0

0 0 1 -1 1 1 -1 -1 -1 1 -1 0 0

1 -1 0 0 1 1 -1 -1 -1 1 -1
都可能是有效的。
编辑:我试图替换的完整代码是

xc <- paste(as.character(sign(diff(x))), collapse = "")
xc <- gsub("1", "+", gsub("-1", "-", xc))
xc <- gsub("0", zero, xc)
peakpat <- sprintf("[+]{%d,}[-]{%d,}", nups, ndowns)
rc <- gregexpr(peakpat, xc)[[1]]
if (rc[1] < 0) return(NULL)
x1 <- rc
x2 <- rc + attr(rc, "match.length")
attributes(x1) <- NULL
attributes(x2) <- NULL


(see pracma::findpeaks()).这段代码是 * 非常 * 慢,所以我试图解决它使用整数.到目前为止,我有

xc2 <- sign(diff(x))
    changepoints <- cumsum(abs(c(1, diff(xc2) != 0)))
    group_size <- tabulate(changepoints)
    lag <- c(NA, group_size[seq_len(length(group_size) - 1)])
    lead <- c(group_size[2:length(group_size)], NA)
    rc1 <- rep(0L, length(xc2))
    rc1[xc2 == 1 & rep(group_size >= nups, group_size) & rep(lead >= ndowns, group_size)] <- 1L
    rc1[xc2 == -1 & rep(group_size >= ndowns, group_size) & rep(lag >= nups, group_size)] <- -1L
    rc1_backup <- rc1
    rc1[rc1 == 0] <- -1
    x1 <- which(diff(c(0, rc1)) > 0)
    rc1 <- rc1_backup
    rc1[rc1 == 0] <- 1
    x2 <- which(diff(c(rc1, 0)) > 0) + 1


这几乎工作......但不完全。

vi4fp9gy

vi4fp9gy1#

尝试

> x <- c(1, -1, 1, 1, -1, -1, -1, 1, -1)

> which(diff(c(0, x)) > 0)
[1] 1 3 8

字符串

dffbzjpn

dffbzjpn2#

也许是这边

> (r <- which(diff(c(0L, cumsum(c(FALSE, diff(x) > 0L)) + 1L)) == 1L))
[1] 1 3 8
> c(r[-1], if (identical(tail(r, 1), len <- length(x))) NULL else len + 1L)
[1]  3  8 10

字符串

  • 数据类型:*
> dput(x)
c(1, -1, 1, 1, -1, -1, -1, 1, -1)

t98cgbkg

t98cgbkg3#

另一种方式,使用逻辑条件:

f <- function(x, n = 0){
  # Create the logical vector from conditions
  cond <- x == x[1] & c(0, x[-length(x)]) != x[1]
  
  #Start and ending indices
  start <- which(cond)
  end <- c(start[-1], length(x) + 1)
  
  #Subset based on size, n is the minimum number of elements (defaults to 0)
  wh <- which(tapply(x, cumsum(cond), FUN = length) > n)

  #Returns a list of start and end indices
  list(start = start[wh], end = end[wh])
}

#Starting with 1
f(x = c(1, -1, 1, 1, -1, -1, -1, 1, -1))
# $start
# [1] 1 3 8
# 
# $end
# [1]  3  8 10

#Starting with -1
f(x = c(-1, -1, 1, 1, -1, -1, -1, 1, -1))
# $start
# [1] 1 5 9
# 
# $end
# [1]  5  9 10

#Minimum 4 elements in the group
f(x <- c(1, -1, 1, 1, -1, -1, -1, 1, -1), n = 4)
# $start
# [1] 3
# 
# $end
# [1] 8

字符串

8gsdolmq

8gsdolmq4#

编辑以满足OP的更改:假设:

  • 列表可能以1开头,但从不以-1开头
  • 列表可能以-1结尾,而不是1
  • 列表可以开始、结束或包含0,但不会出现在1、-1模式的中间
# data:
testvec <- c(1, -1,  1,  1, -1, -1, -1,  1, -1)
testvec2 <- c(0, 0, 1, -1, 1, 1, -1, -1, -1, 1, -1)

cutup2 <- function(testvec, n = 1, m = 1) {
  # helper - do run length encoding
  testrle <- rle(testvec)
  # helper - define the break positions based on the criteria provided
  # note that the final break will be outside the length of the vector
  # as 'ends' are defined as the position _after_ the specific sequence.
  breaks = c(1, cumsum(testrle$lengths)+1)
  
  #define the data frame - number of rows should equal # of 1s in the RLE
  data.frame(
    start = breaks[c(testrle$values == 1, FALSE)],
    end = breaks[c(FALSE,c(testrle$values == -1))],
    num = testrle$lengths[testrle$values == 1],
    negnum = testrle$lengths[testrle$values == -1]
  ) |> dplyr::filter(num >= n & negnum >= m)
}

字符串
给出:

> cutup2(testvec,1,1)
  start end num negnum
1     1   3   1      1
2     3   8   2      3
3     8  10   1      1
> cutup2(testvec,2,2)
  start end num negnum
1     3   8   2      3
> cutup2(testvec2,1,1)
  start end num negnum
1     3   5   1      1
2     5  10   2      3
3    10  12   1      1
> cutup2(testvec2,2,2)
  start end num negnum
1     5  10   2      3


说明:
对于“start”,我们使用每个集合中第一个元素的位置。
对于“end”,我们使用NEXT集合的第一个元素的位置。
这意味着我们的断点都是起始位置,可以通过取向量1和(长度的累积和+1)c(1, cumsum(testrle$lengths)+1)来列出
开始是根据数据集中1类型运行的顺序选择的,并且永远不能是最后一个:[c(testrle$values == 1, FALSE)]
根据数据集中-1类型的运行序列选择结束,通过插入FALSEbreaks[c(FALSE,c(testrle$values == -1))]向结束移动一个位置(我们希望NEXT序列的开始)
对于n和m(我称之为numnegnum),我们只需要分别为1-1的rle的长度。
然后我通过nm进行过滤-我已经使用了dplyr::filter(),但是如果你不喜欢使用外部包,有一些简单的R基方法可以做到这一点。
编辑:测试与所有提供的例子:

testvecs <- list(c(1, -1,  1,  1, -1, -1, -1,  1, -1),
                 c(0, 0, 1, -1, 1, 1, -1, -1, -1, 1, -1),
                 c(1, -1, 1, 1, -1, -1, -1, 1, -1, 0, 0),
                 c(0, 0, 1, -1, 1, 1, -1, -1, -1, 1, -1, 0, 0),
                 c(1, -1, 0, 0, 1, 1, -1, -1, -1, 1, -1))

lapply(testvecs, cutup2, n = 1, m = 1)
lapply(testvecs, cutup2, n = 2, m = 2)
> lapply(testvecs, cutup2, n = 1, m = 1)
[[1]]
  start end num negnum
1     1   3   1      1
2     3   8   2      3
3     8  10   1      1

[[2]]
  start end num negnum
1     3   5   1      1
2     5  10   2      3
3    10  12   1      1

[[3]]
  start end num negnum
1     1   3   1      1
2     3   8   2      3
3     8  10   1      1

[[4]]
  start end num negnum
1     3   5   1      1
2     5  10   2      3
3    10  12   1      1

[[5]]
  start end num negnum
1     1   3   1      1
2     5  10   2      3
3    10  12   1      1

> lapply(testvecs, cutup2, n = 2, m = 2)
[[1]]
  start end num negnum
1     3   8   2      3

[[2]]
  start end num negnum
1     5  10   2      3

[[3]]
  start end num negnum
1     3   8   2      3

[[4]]
  start end num negnum
1     5  10   2      3

[[5]]
  start end num negnum
1     5  10   2      3
bwleehnv

bwleehnv5#

最后,rle()给了我所需要的,我只需要正确的子集。

rc <- rle(xc2)
  vals <- rc$values
  lens <- rc$lengths
  rc_len <- length(rc$lengths)
  lead <- c(vals[2:rc_len], NA)
  lead_lens <- c(lens[2:rc_len], NA)
  pos_peak_start <- which(vals == 1 & lens >= nups & lead == -1 & lead_lens >= ndowns)
  x1 <- (cumsum(c(0, lens)) + 1)[pos_peak_start]
  lag <- c(NA, vals[-rc_len])
  lag_lens <- c(NA, lens[-rc_len])
  pos_peak_end <- which(vals == -1 & lens >= ndowns & lag == 1 & lag_lens >= nups)
  x2 <- (cumsum(lens) + 1)[pos_peak_end]

字符串

相关问题