在 R 中的时间序列中多次找到第一个值
find the first value multiple times in a time series in R
我试图在一个时间序列中多次查找特定值,在本例中为第一个值。数据看起来像这样
data <- data.table::data.table(value = c(0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1),
time = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21))
现在我想找到 value == 1
中的第一个值并给我时间。
时间的结果应该如下所示:4, 14, 18
如果解决方案灵活,您可以跳过后面的少量零,那也会很有帮助。
对于这种情况,time: 4, 18 的结果将如下所示,因为您可以跳过中间的 2 个零。
我已经尝试过 which(min)
的解决方案,但它只给我第一个值,而不是下面的第一个值。
您需要为每个连续的 运行 个 0&1 创建一个组。然后你可以按这个分组并在每个中取第一行。
data %>%
mutate(group = cumsum(value != lag(value , 1, TRUE))) %>%
group_by(group) %>%
filter(row_number()==1, value == 1) %>%
select(-group)
使用 data.table
rleid
-
data$time[!duplicated(data.table::rleid(data$value)) & data$value == 1]
#[1] 4 14 18
如果你想跳过一些连续零的计数,你可以使用这个函数。
skip_zero <- function(df, n = 0) {
inds <- data.table::rleid(df$value)
df$value[ave(inds, inds, FUN = length) <= n & df$value == 0] <- 1
inds <- data.table::rleid(df$value)
df$time[!duplicated(inds) & df$value == 1]
}
skip_zero(data)
#[1] 4 14 18
skip_zero(data, 2)
#[1] 4 14
with(
rle(data$value),
c(1, 1 + cumsum(lengths))[which(values == 1)]
)
# [1] 4 14 18
OP 提到 he/she 喜欢 data.table 方式。
因此,这是一种 data.table 方法,它使用 shift()
和 [=38= 在 value
列中查找 子序列 的出现]加入:
library(data.table)
data[, shift(value, 1:0)][.(0, 1), on = .(V1, V2), which = TRUE]
[1] 4 14 18
在这里,我们在 value
中寻找子序列 (0, 1)
的出现。这可以很容易地扩展到涵盖任意子序列,例如,
data[, shift(value, 3:0)][.(0, 0, 0, 1), on = .(V1, V2, V3, V4), which = TRUE]
[1] 4 14
跳过两个后续零的出现。
说明
待完成
扩展
通用函数待完成
我试图在一个时间序列中多次查找特定值,在本例中为第一个值。数据看起来像这样
data <- data.table::data.table(value = c(0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1),
time = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21))
现在我想找到 value == 1
中的第一个值并给我时间。
时间的结果应该如下所示:4, 14, 18
如果解决方案灵活,您可以跳过后面的少量零,那也会很有帮助。 对于这种情况,time: 4, 18 的结果将如下所示,因为您可以跳过中间的 2 个零。
我已经尝试过 which(min)
的解决方案,但它只给我第一个值,而不是下面的第一个值。
您需要为每个连续的 运行 个 0&1 创建一个组。然后你可以按这个分组并在每个中取第一行。
data %>%
mutate(group = cumsum(value != lag(value , 1, TRUE))) %>%
group_by(group) %>%
filter(row_number()==1, value == 1) %>%
select(-group)
使用 data.table
rleid
-
data$time[!duplicated(data.table::rleid(data$value)) & data$value == 1]
#[1] 4 14 18
如果你想跳过一些连续零的计数,你可以使用这个函数。
skip_zero <- function(df, n = 0) {
inds <- data.table::rleid(df$value)
df$value[ave(inds, inds, FUN = length) <= n & df$value == 0] <- 1
inds <- data.table::rleid(df$value)
df$time[!duplicated(inds) & df$value == 1]
}
skip_zero(data)
#[1] 4 14 18
skip_zero(data, 2)
#[1] 4 14
with(
rle(data$value),
c(1, 1 + cumsum(lengths))[which(values == 1)]
)
# [1] 4 14 18
OP 提到
因此,这是一种 data.table 方法,它使用 shift()
和 [=38= 在 value
列中查找 子序列 的出现]加入:
library(data.table)
data[, shift(value, 1:0)][.(0, 1), on = .(V1, V2), which = TRUE]
[1] 4 14 18
在这里,我们在 value
中寻找子序列 (0, 1)
的出现。这可以很容易地扩展到涵盖任意子序列,例如,
data[, shift(value, 3:0)][.(0, 0, 0, 1), on = .(V1, V2, V3, V4), which = TRUE]
[1] 4 14
跳过两个后续零的出现。
说明
待完成
扩展
通用函数待完成