获取特定长度的连续整数并从第一个值中采样
Get runs of consecutive integers of certain length and sample from first values
我正在尝试创建一个函数,它将 return 向量子集的第一个整数,这样子集的值是离散的,增加 1,并且具有指定的长度。
例如,使用输入数据 'v' 和指定长度 'l' 3:
v <- c(3, 4, 5, 6, 15, 16, 25, 26, 27)
l <- 3
长度为 3 的连续值的可能子向量为:
c(3, 4, 5)
c(4, 5, 6)
c(25, 26, 27)
然后我想随机选择这些向量之一和 return first/lowest 数字,即 3、4 或 25。
这是一种基于 R
:
的方法
首先,我们创建所有可能的长度为 length
的子向量。接下来,我们根据向量的 cumsum
等于 1
对向量列表进行子集化。 is.na
测试确保最后包含 NA
的向量也被过滤掉。然后我们只需将剩余的向量绑定到一个矩阵中并对第一列进行采样。
SampleSequencialVectors <- function(vec, length){
all.vecs <- lapply(seq_along(vec),function(x)vec[x:(x+(length-1))])
seq.vec <- all.vecs[sapply(all.vecs,function(x) all(diff(x) == 1 & !is.na(diff(x))))]
sample(do.call(rbind,seq.vec)[,1],1)
}
replicate(10, SampleSequencialVectors(v, 3))
# [1] 3 4 3 3 4 4 25 25 3 25
或者如果您更喜欢 tidyverse 类型的方法:
SampleSequencialVectorsPurrr <- function(vec, length){
vec %>%
seq_along %>%
purrr::map(~vec[.x:(.x+(length-1))]) %>%
purrr::keep(~ all(diff(.x) == 1 & !is.na(diff(.x)))) %>%
purrr::invoke(rbind,.) %>%
{sample(.[,1],size = 1)}
}
replicate(10, SampleSequencialVectorsPurrr(v, 3))
[1] 4 25 25 3 25 4 4 3 4 25
自鸣得意 -- cgwtools::seqle
类似于 rle
,但您可以在 运行 中指定所需的增量。 seqle(x, incr = 0,..)
等同于 rle(x)
然后只需从结果中获取 运行 长度和起始值。
Base R 两行:请注意此解决方案假定 v 已排序。
consec_seq <- sapply(seq_along(v), function(i)split(v, abs(v - v[i]) > 1)[1])
consec_seq[lengths(consec_seq) == l][sample.int(l, 1)]
作为可重用函数(不假设 v 已排序):
conseq_split_sample <- function(vec, n){
v <- sort(vec)
consec_seq <- sapply(seq_along(v), function(i)split(v, abs(v - v[i]) > 1)["FALSE"])
consec_seq[lengths(consec_seq) == n][sample.int(n, 1)]
}
conseq_split_sample(v, l)
数据:
l <- 3
v <- c(3, 4, 5, 6, 15, 16, 25, 26, 27)
- 将向量拆分为 运行 个连续值*:
split(v, cumsum(c(1L, diff(v) != 1)))
- Select 运行s 的长度超过或等于限制:
runs[lengths(runs) >= lim]
- 从每个 运行、select 可能的第一个值 (
x[1:(length(x) - lim + 1)]
)。
从所有可能的第一个值中,样本 1。
runs = split(v, cumsum(c(1L, diff(v) != 1)))
first = lapply(runs[lengths(runs) >= lim], function(x) x[1:(length(x) - lim + 1)])
sample(unlist(first), 1)
这里我们遍历足够长度的 运行s,而不是所有单个值(参见其他答案),因此 可能 在较大的向量上更快(还没有测试过)。
使用data.table
稍微紧凑一些:
sample(data.table(v)[ , if(.N >= 3) v[1:(length(v) - lim + 1)],
by = .(cumsum(c(1L, diff(v) != 1)))]$V1, 1)
*漂亮的规范的学分:How to split a vector into groups of consecutive sequences?.
我正在尝试创建一个函数,它将 return 向量子集的第一个整数,这样子集的值是离散的,增加 1,并且具有指定的长度。
例如,使用输入数据 'v' 和指定长度 'l' 3:
v <- c(3, 4, 5, 6, 15, 16, 25, 26, 27)
l <- 3
长度为 3 的连续值的可能子向量为:
c(3, 4, 5)
c(4, 5, 6)
c(25, 26, 27)
然后我想随机选择这些向量之一和 return first/lowest 数字,即 3、4 或 25。
这是一种基于 R
:
首先,我们创建所有可能的长度为 length
的子向量。接下来,我们根据向量的 cumsum
等于 1
对向量列表进行子集化。 is.na
测试确保最后包含 NA
的向量也被过滤掉。然后我们只需将剩余的向量绑定到一个矩阵中并对第一列进行采样。
SampleSequencialVectors <- function(vec, length){
all.vecs <- lapply(seq_along(vec),function(x)vec[x:(x+(length-1))])
seq.vec <- all.vecs[sapply(all.vecs,function(x) all(diff(x) == 1 & !is.na(diff(x))))]
sample(do.call(rbind,seq.vec)[,1],1)
}
replicate(10, SampleSequencialVectors(v, 3))
# [1] 3 4 3 3 4 4 25 25 3 25
或者如果您更喜欢 tidyverse 类型的方法:
SampleSequencialVectorsPurrr <- function(vec, length){
vec %>%
seq_along %>%
purrr::map(~vec[.x:(.x+(length-1))]) %>%
purrr::keep(~ all(diff(.x) == 1 & !is.na(diff(.x)))) %>%
purrr::invoke(rbind,.) %>%
{sample(.[,1],size = 1)}
}
replicate(10, SampleSequencialVectorsPurrr(v, 3))
[1] 4 25 25 3 25 4 4 3 4 25
自鸣得意 -- cgwtools::seqle
类似于 rle
,但您可以在 运行 中指定所需的增量。 seqle(x, incr = 0,..)
等同于 rle(x)
然后只需从结果中获取 运行 长度和起始值。
Base R 两行:请注意此解决方案假定 v 已排序。
consec_seq <- sapply(seq_along(v), function(i)split(v, abs(v - v[i]) > 1)[1])
consec_seq[lengths(consec_seq) == l][sample.int(l, 1)]
作为可重用函数(不假设 v 已排序):
conseq_split_sample <- function(vec, n){
v <- sort(vec)
consec_seq <- sapply(seq_along(v), function(i)split(v, abs(v - v[i]) > 1)["FALSE"])
consec_seq[lengths(consec_seq) == n][sample.int(n, 1)]
}
conseq_split_sample(v, l)
数据:
l <- 3
v <- c(3, 4, 5, 6, 15, 16, 25, 26, 27)
- 将向量拆分为 运行 个连续值*:
split(v, cumsum(c(1L, diff(v) != 1)))
- Select 运行s 的长度超过或等于限制:
runs[lengths(runs) >= lim]
- 从每个 运行、select 可能的第一个值 (
x[1:(length(x) - lim + 1)]
)。 从所有可能的第一个值中,样本 1。
runs = split(v, cumsum(c(1L, diff(v) != 1))) first = lapply(runs[lengths(runs) >= lim], function(x) x[1:(length(x) - lim + 1)]) sample(unlist(first), 1)
这里我们遍历足够长度的 运行s,而不是所有单个值(参见其他答案),因此 可能 在较大的向量上更快(还没有测试过)。
使用data.table
稍微紧凑一些:
sample(data.table(v)[ , if(.N >= 3) v[1:(length(v) - lim + 1)],
by = .(cumsum(c(1L, diff(v) != 1)))]$V1, 1)
*漂亮的规范的学分:How to split a vector into groups of consecutive sequences?.