假设我有一个具有不同组长度的不同组的时间序列。我如何按组随机选择连续的行,并作为每个相应组长度的函数(例如,每组的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(。