r-按组按组长度的比例随机选择连续行

  • 本文关键字:随机 选择 连续 r dplyr data.table
  • 更新时间 :
  • 英文 :


假设我有一个具有不同组长度的不同组的时间序列。我如何按组随机选择连续的行,并作为每个相应组长度的函数(例如,每组的10%(

我使用这里的代码进行了尝试,但它不适用于我的数据。

library(data.table)
library(dplyr)
# Creating a dummy dataframe:
cell <- c(rep("a", 100), rep("b", 80),  rep("c", 60),  rep("d", 40),  rep("e", 20), rep("f", 10))
df <- data.frame(cell) %>% group_by(cell) %>% mutate(Time = row_number()) %>% as.data.table()
df_subset <- df[df[ , (sample(.I[-.N], 1)) + (0:(0.1*.N)), by = cell]$V1]

子集的问题:

  • 由于所选行的数量不能完全反映组长度,因此它不以某种方式采用比例(我预计为10、8、6、4、2和1个样本(
  • 一个更大的问题是,对于更大的比例,它实际上是在每组长度之外进行采样的。例如,如果它选择行长度为100的行99,则每超过2的随机采样都会在我的数据帧中创建NA

我最后写了自己的函数,但我想知道是否有一种很好的dplyr或data.table方法来处理这个问题?

也许类似于:

df[df[ , {
k = ceiling(0.1 * .N)
sample(head(.I, -k), 1L) + (0L:(k-1L))
}, cell]$V1]

我们的想法是从索引向量中选取一个样本,但样本必须距离向量的末尾至少k个空间,这样,如果我们碰巧从后面选取第k个元素,我们将使用从后面倒数第k个的元素。为此,我们使用head(.I, -k)

head(.I, -k)移除最后k个索引。sample(..., 1L)随机选取一个元素,因为当我们需要k个元素时,我们选择这个选取的元素和随后的k-1个元素。

您可以创建一个执行连续随机采样的用户定义函数,然后将其与dplyr:一起使用

consecutive_subset <- function(x, prop) {
i_start <- sample(1:(length(x)-floor(length(x)*prop)), 1)
i_end <- (i_start+floor(length(x)*prop)-1)
return(x[i_start:i_end])
}

此函数返回向量x的连续元素的随机样本,样本长度确定为length(x)的比例(例如,您的问题中的"每组的10%"(。如果length(x)不能被prop整除,则对样本长度的长度进行地板化以避免误差。根据x的定义,此函数也不应在其边界之外进行采样。

然后,您可以对数据进行分组,并使用summarise_all:将此函数应用于每组的每一列

result <- df %>%
group_by(cell) %>%
summarise_all(~ consecutive_subset(., 0.1))

使用summarise(result, n())检查每个子集的长度是否正确,得到:

# A tibble: 6 x 2
cell  `n()`
<chr> <int>
1 a        10
2 b         8
3 c         6
4 d         4
5 e         2
6 f         1

我用来解决它的调整函数来自上面的链接:

df_subset <- df[as.logical(ave(df$cell, df$cell, FUN = function(x){
i <- seq_along(x)
i %in% (sample(head(i, -(length(i)*0.25)), 1) + 0:((length(i)*0.25)-1))
})), ]

值得注意的是,如果列是一个因子,则需要对相应的列使用as.character()(此处为df$cell(。

最新更新