【问题标题】:find number sequence falls within ONE adjacent number (previous and next) by group按组查找数字序列属于一个相邻数字(上一个和下一个)
【发布时间】:2016-07-28 21:50:43
【问题描述】:

T={t|t=1,2,3..T} 为时间(序列号)对于每个组,在每个t 时/如果发生序列,我们需要确定序列(它是一个数字,假设它是@987654323 @) 在 {K-1,K,K+1} 的集合中,其中Kt-1 的前一个序列号。例如,如果前一个序列号K=4,对于下一个序列X,如果X落在[3,4,5]之内。那么这个 X 满足要求。如果序列中的每个 X 都满足要求,则该组满足要求并将其标记为 TRUE。

我知道 for 循环可以解决问题,但我有大量观察,在循环中执行它非常慢。我知道cummax 可以帮助快速找到非递减序列。我想知道有没有像cummax 这样的快速解决方案。

seq <- c(1,2,1,2,3,1,2,3,1,2,1,2,2,3,4)
group <- rep(letters[1:3],each=5)
dt <- data.frame(group,seq)

> dt
  group seq
1      a   1
2      a   2
3      a   1
4      a   2
5      a   3
6      b   1
7      b   2
8      b   3
9      b   1
10     b   2
11     c   1
12     c   2
13     c   2
14     c   3
15     c   4

想要的输出:

y label
a:true
b:false
c:true

【问题讨论】:

    标签: r data.table dplyr


    【解决方案1】:

    可以使用diff函数检查相邻序列是否满足条件:

    library(dplyr)
    dt %>% group_by(group) %>% summarize(label = all(abs(diff(seq)) <= 1))
    
    # A tibble: 3 x 2
    #   group label
    #  <fctr> <lgl>
    #1      a  TRUE
    #2      b FALSE
    #3      c  TRUE
    

    这里是对应的data.table版本:

    library(data.table)
    setDT(dt)[, .(label = all(abs(diff(seq)) <= 1)), .(group)]
    

    【讨论】:

    • 我忘记了差异。谢谢!我会检查我的数据的速度。
    • data.table 我猜setDT(dt)[, all(abs(seq - shift(seq, fill = 0)) &lt; 2), by = group] 会更惯用
    • @DavidArenburg 不错的建议。没测试。但我认为这会加快速度。
    【解决方案2】:

    你可以这样做:

    is.sequence <- function(x)
        all(apply(head(cbind(x-1, x, x+1), -1) - x[-1] == 0, 1, any))
    
    tapply(dt$seq, dt$group, is.sequence)
    #    a     b     c 
    # TRUE FALSE  TRUE 
    

    【讨论】:

    • 为什么要在tapply 中运行apply
    【解决方案3】:

    这是带有aggregatediff 的基本R 示例

        aggregate(c(1, abs(diff(dt$seq)) * (tail(dt$group, -1) ==
                                            head(dt$group, -1))),
                  dt["group"], function(i) max(i) < 2)
    
      group     x
    1     a  TRUE
    2     b FALSE
    3     c  TRUE
    

    aggregate 的第一个参数是一个向量,它使用diff 并根据当前相邻向量元素是否在同一组中来打开和关闭结果(为零)。

    【讨论】:

    • 我在这里的任何地方都看不到ave,但也许with(dt, tapply(seq, group, function(x) all(abs(diff(x)) &lt; 2))) 也可能是一个基本的替代方案
    • 您对ave 的看法是正确的。我在早期迭代中使用它并丢弃它......这个替代品看起来很棒。
    【解决方案4】:

    我们也可以使用base R中的aggregate

    aggregate(seq~group,dt,  FUN = function(x) all(c(TRUE, 
                                abs((x[-1] - x[-length(x)])) <=1)))
    #  group   seq
    #1     a  TRUE
    #2     b FALSE
    #3     c  TRUE
    

    【讨论】:

      猜你喜欢
      • 2018-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多