r - 按条件过滤 data.table,但每 N 行至少保留一行
问题描述
假设我有这个微不足道的 data.table:
library(data.table)
dt <- data.table(
day = 1:10,
a = c(0, 1, 10, 2, 2.5, 2.3, 2.7, 2.9, 5, 8)
)
我想根据a
. 在这种情况下,a
变化超过 3 的时刻。这是微不足道的:
dt[abs(a - shift(a)) >= 3]
但是,我不想在很长一段时间内丢失信息。因此,如果上述条件没有受到影响,我需要确保没有超过 3 天的“过滤”延伸。
在上述情况下,基于的条件a
满足:
dt[, abs(a - shift(a)) >= 3]
# [1] NA FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE TRUE
-----------------------------
FALSE
请注意,在接近尾声的地方有一段很长的时间。我想到的最好的是
dt[, abs(a - shift(a)) >= 3 | .I %% 3 == 0]
# [1] NA FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE TRUE
---- ----
(即确保每第三行被接受)但它不会放置最好或最少的附加行。
最佳结果将是一个过滤器,它在中间FALSE
有一个TRUE
右(或尽可能多的)打破这条线。
# [1] NA FALSE TRUE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
----
解决方案
也许有人可以复制这一点,data.table
但这是您可能正在寻找的逻辑。为了清楚起见,我分离了test
,run_length
和result
,但如果需要,可以将逻辑组合或包装在一个函数中。
这将保留所有行
test
是TRUE
或者
和 的每一
N
行中的每一TRUE
行FALSE
。
这样,所有TRUE
s 都由第一个条件保留,第二个条件捕获N
每个条纹的每个元素,因此FALSE
也捕获了一些 s。-
library(dplyr)
N <- 3
dt %>%
mutate(
test = abs(a - lag(a)) >= N, # flag change(a) >= N
run_length = sequence(rle(test)$lengths), # seq along streaks of TRUE and FALSE
result = test | run_length %% N == 0
) # %>%
# filter(result) # uncomment this to get final dt
day a test run_length result
1 1 0.0 NA 1 NA
2 2 1.0 FALSE 1 FALSE
3 3 10.0 TRUE 1 TRUE
4 4 2.0 TRUE 2 TRUE
5 5 2.5 FALSE 1 FALSE
6 6 2.3 FALSE 2 FALSE
7 7 2.7 FALSE 3 TRUE
8 8 2.9 FALSE 4 FALSE
9 9 5.0 FALSE 5 FALSE
10 10 8.0 TRUE 1 TRUE
在data.table
(我猜) -
dt[, (test <- abs(a - shift(a)) >= N) | sequence(rle(test)$lengths) %% N == 0]
[1] NA FALSE TRUE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
推荐阅读
- codenameone - 我可以通过 java codenameone 移动应用程序开始 Zoom 视频会议吗?
- mongodb - JanusGraph 的自定义存储后端
- kubernetes - pod 有未绑定的立即 PersistentVolumeClaims(重复 3 次)
- laravel - 刀片 Laravel 中 foreach 中的字符损坏
- javascript - 修剪用户名 Laravel + JS
- sql - 查询将数据从一个表列移动到另一个表
- elasticsearch - 为什么 Elasticsearch ignore_malformed 会向索引添加格式错误的值?
- bash - 如何正确编写 bash 可执行文件
- javascript - 反应 Dropzone 以在 drop 上应用 css
- pdf - 如何使用 autocmd 将 PDF 文件转换为 TXT 文件?