如果 R 中的组值在特定时间内彼此发生,则删除行
Removing rows if they occur within a certain time of each other by a group value in R
我的数据 df
如下所示:
Row Timestamp ID
1 0020-06-29 12:14:00 B
2 0020-06-29 12:27:00 A
3 0020-06-29 12:27:22 B
4 0020-06-29 12:28:30 A
5 0020-06-29 12:43:00 B
6 0020-06-29 12:44:00 C
7 0020-06-29 12:45:00 B
8 0020-06-29 12:55:00 A
9 0020-06-29 12:57:00 C
10 0020-06-29 13:04:00 B
Timestamp
表示读数的日期和时间,ID
表示标签识别码。
我想做的是删除任何 Timestamp
相同的 ID
发生在前一个时间戳的 5 分钟内。因此,虽然 ID
A 出现在 Row
2 和 Row
4 中,但由于数据帧的两行发生在彼此相隔 5 分钟以内,我们将删除 Row
4但保留 Row
2 和 Row
8,对于 ID A,它在 18 分钟后发生。
更新:第一个时间戳应该是先例,所有后续时间戳都应该保留或从那时起删除。因此,如果我们有 3 个时间戳对应于相同的 ID,时间间隔分别为 4.5 分钟和 2 分钟,时间戳 1 和 2 以及时间戳 2 和 3 之间,我想删除时间戳 2 并保留 1 和 3。这我们保留的下一个时间戳将是在时间戳 3 之后至少 5 分钟出现的时间戳,依此类推。
我尝试了以下方法:
first_date <- df$Timestamp[1:(length(df$Timestamp)-1)]
second_date <- df$Timestamp[2:length(df$Timestamp)]
second_gap <- difftime(second_date, first_date, units="mins")
dup_index <- second_gap>5 # set this as a 5-minute threshold
dup_index <- c(TRUE, dup_index)
df_cleaned <- df[dup_index, ]
但这会删除彼此相隔 5 分钟内的所有观察结果,并且不会考虑 ID
。我通常只会 subset
但我正在处理大约 180 个独特的 ID
s.
假设我上面的评论没有发生,可能的解决方案如下:
library(tidyverse)
library(lubridate)
elapsed <- function(x)
{
y <- abs(as.duration(x[2:length(x)] %--% x[1:(length(x)-1)]))
y >= 5*60
}
df %>%
group_split(ID) %>%
map_dfr(~ .[c(T, if (nrow(.) > 1) elapsed(.$Timestamp)),]) %>%
arrange(Row)
输出:
# A tibble: 8 × 3
Row Timestamp ID
<int> <chr> <chr>
1 1 0020-06-29 12:14:00 B
2 2 0020-06-29 12:27:00 A
3 3 0020-06-29 12:27:22 B
4 5 0020-06-29 12:43:00 B
5 6 0020-06-29 12:44:00 C
6 8 0020-06-29 12:55:00 A
7 9 0020-06-29 12:57:00 C
8 10 0020-06-29 13:04:00 B
我的数据 df
如下所示:
Row Timestamp ID
1 0020-06-29 12:14:00 B
2 0020-06-29 12:27:00 A
3 0020-06-29 12:27:22 B
4 0020-06-29 12:28:30 A
5 0020-06-29 12:43:00 B
6 0020-06-29 12:44:00 C
7 0020-06-29 12:45:00 B
8 0020-06-29 12:55:00 A
9 0020-06-29 12:57:00 C
10 0020-06-29 13:04:00 B
Timestamp
表示读数的日期和时间,ID
表示标签识别码。
我想做的是删除任何 Timestamp
相同的 ID
发生在前一个时间戳的 5 分钟内。因此,虽然 ID
A 出现在 Row
2 和 Row
4 中,但由于数据帧的两行发生在彼此相隔 5 分钟以内,我们将删除 Row
4但保留 Row
2 和 Row
8,对于 ID A,它在 18 分钟后发生。
更新:第一个时间戳应该是先例,所有后续时间戳都应该保留或从那时起删除。因此,如果我们有 3 个时间戳对应于相同的 ID,时间间隔分别为 4.5 分钟和 2 分钟,时间戳 1 和 2 以及时间戳 2 和 3 之间,我想删除时间戳 2 并保留 1 和 3。这我们保留的下一个时间戳将是在时间戳 3 之后至少 5 分钟出现的时间戳,依此类推。
我尝试了以下方法:
first_date <- df$Timestamp[1:(length(df$Timestamp)-1)]
second_date <- df$Timestamp[2:length(df$Timestamp)]
second_gap <- difftime(second_date, first_date, units="mins")
dup_index <- second_gap>5 # set this as a 5-minute threshold
dup_index <- c(TRUE, dup_index)
df_cleaned <- df[dup_index, ]
但这会删除彼此相隔 5 分钟内的所有观察结果,并且不会考虑 ID
。我通常只会 subset
但我正在处理大约 180 个独特的 ID
s.
假设我上面的评论没有发生,可能的解决方案如下:
library(tidyverse)
library(lubridate)
elapsed <- function(x)
{
y <- abs(as.duration(x[2:length(x)] %--% x[1:(length(x)-1)]))
y >= 5*60
}
df %>%
group_split(ID) %>%
map_dfr(~ .[c(T, if (nrow(.) > 1) elapsed(.$Timestamp)),]) %>%
arrange(Row)
输出:
# A tibble: 8 × 3
Row Timestamp ID
<int> <chr> <chr>
1 1 0020-06-29 12:14:00 B
2 2 0020-06-29 12:27:00 A
3 3 0020-06-29 12:27:22 B
4 5 0020-06-29 12:43:00 B
5 6 0020-06-29 12:44:00 C
6 8 0020-06-29 12:55:00 A
7 9 0020-06-29 12:57:00 C
8 10 0020-06-29 13:04:00 B