【问题标题】:Finding monotonous sequence along with taking sequence restart on reaching maximum into account寻找单调序列以及在达到最大值时重新启动序列
【发布时间】:2017-05-17 16:44:42
【问题描述】:

我有一个 data.table 说 dt

name <- letters[1:22]
score <- c(42, 82, 43, 32, 47, 48, 49, 50, 54, 59, 
           76, 9, 13, 88, 91, 99, 4, 6, 8, 12, 14, 15)
class <- rep(c('c1', 'c2', 'c3'), c(7, 3, 12))
dt <- data.table(name, score, class)

看起来像:

> dt
    name score class
 1:    a    42    c1
 2:    b    82    c1
 3:    c    43    c1
 4:    d    32    c1
 5:    e    47    c1
 6:    f    48    c1
 7:    g    49    c1
 8:    h    50    c2
 9:    i    54    c2
10:    j    59    c2
11:    k    76    c3
12:    l     9    c3
13:    m    13    c3
14:    n    88    c3
15:    o    91    c3
16:    p    99    c3
17:    q     4    c3
18:    r     6    c3
19:    s     8    c3
20:    t    12    c3
21:    u    14    c3
22:    v    15    c3

我只需要那些遵循每个班级分数单调序列的记录。在这种情况下,只有 c1 类的分数为 42、43、47、48 49 的记录,给定类最多可以有 3 个连续的乱序分数。因此,第 2 行(分数 = 82)也是一个乱序分数。

c2 类得分为 50、54、59 的记录。

在“c3”类记录中,得分为 76、88、91、99、04、06、08、12、14、15。此处序列已达到最大值(99),然后重新开始。 “c3”类中的分数 09 和 13 超出了单调序列,因此需要删除。

我想删除那些在 c1、c2、c3 类中提到的分数不是按顺序排列的记录。总共有 100 万条记录。

最终的输出必须是这样的。

> dt
    name score class
 1:    a    42    c1
 2:    c    43    c1
 3:    e    47    c1
 4:    f    48    c1
 5:    g    49    c1
 6:    h    50    c2
 7:    i    54    c2
 8:    j    59    c2
 9:    k    76    c3
10:    n    88    c3
11:    o    91    c3
12:    p    99    c3
13:    q     4    c3
14:    r     6    c3
15:    s     8    c3
16:    t    12    c3
17:    u    14    c3
18:    v    15    c3

为了找到单调的序列我试过了:

dt <- dt[, .SD[score == cummax(score)],class]

但这也删除了达到最大值后重新启动的序列。

实际上序列重启的最大值为 999999,虽然在这个例子中我取最大值为 99。我该怎么做。

【问题讨论】:

  • 我不确定您的收录条件是否明确。你能尝试更明确一点吗?
  • 序列必须是单调的,我需要从它们之间删除任何乱序,同时还必须注意序列重启
  • dt[, keep := score >= cummax(shift(score, fill = first(score))), by = .(class, rleid(score == 99))]还要注意单调序列,最大化条件,但它正在从类 c1 中删除第 3 行到第 7 行,因为前面提到了分数 82,尽管那是无序的,必须删除
  • 例如,我们怎么知道从c3中排除76?选择序列最低元素的条件是什么?
  • 每个类的第一个元素是最低的,否则我们看上一个类的前几个seq

标签: r dataframe data.table


【解决方案1】:

这主要可以使用dplyr来完成

dts <- dt %>% 
       group_by(class) %>% 
       mutate(f = ifelse( (score - lead(score) > 0 & lag(score) - score <0) | 
                          (score - lead(score) < 0 & lag(score) - score > 0) , 1, 0)) %>%
       mutate(f = ifelse(is.na(f), 0, f)) %>%
       mutate(g = ifelse((lead(f) == 1 & f == 1)| (lag(f) == 1 & f == 1 ), 2, 0) )) %>%
       filter(f + g != 1)

正如我所说,这将主要帮助您实现目标。这样做的问题是您将获得 19 个观察值(保留 id = m)而不是 18 个。您可以做的是在 dts 上重新运行它以消除 id = m。或者,如果这是一个较大集合的子集,您可以使用 forwhile 循环。这是因为leadlag 函数只检查上下一个索引。

另一种选择是一种老派的技术,称为 push-pop 技术,但我会远离它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 2013-10-22
    • 1970-01-01
    相关资源
    最近更新 更多