根据行中的最小和最大非零元素对数据帧进行二次采样

时间:2019-07-04 19:01:28

标签: r

我有一个包含许多零元素的计数矩阵:

my.matrix <- as.data.frame(matrix(rbinom(100 * 1000, 1, 0.5), ncol = 100, nrow = 1000))

(实际上,非零整数的范围在1到12,000之间,但我找不到更好的示例。我的数据集不只包含0和1)。

我想随机选择n行(例如,n = 100),其中至少x x但不超过y个非零元素:

n = number of randomly selected rows 
x = minimum amount of non-zero elements in a row
y = maximum amount of non-zero elements in a row

该怎么做? 预先谢谢你!

2 个答案:

答案 0 :(得分:2)

为可复制的随机数据设置种子:

set.seed(2)
my.matrix <- as.data.frame(matrix(rbinom(100 * 1000, 1, 0.5), ncol = 100, nrow = 1000))

applyrowSums之类的功能会将数据转换为matrix。如果包含的列为character(如果有),则将转换所有内容,并且某些行为可能不会如您所愿。使用isnum只是为了确保您不会无意中将其包括在内(即使此实际示例数据没有错):

isnum <- sapply(my.matrix, is.numeric)
sums <- rowSums(my.matrix[,isnum] != 0)
head(sums)
# [1] 51 60 53 45 42 56
table(sums)
# sums
# 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 
#  2  2  1  7 11 20 21 37 36 49 46 64 72 71 59 79 72 77 76 52 48 33 21 14 11 10 
# 62 63 64 70 
#  1  5  2  1 

从这里开始,只需手动划分范围即可。

my.matrix[ 37 < sums & sums < 40, 1:4 ]
#     V1 V2 V3 V4
# 69   0  0  1  1
# 202  1  0  0  1
# 228  0  1  0  0
# 293  1  0  1  0
# 306  0  1  0  0
# 363  0  1  1  0
# 810  0  0  1  1
# 890  1  0  1  1

您也可以使用dplyr::betweendata.table::between获得更简洁的代码,尽管它并没有为此添加任何功能。

关于采样,获得此信息后,它就是直接采样:

ind <- which(37 < sums & sums < 40)
ind <- sample(ind, min(length(ind), 100))
my.matrix[ ind, 1:4 ]
#     V1 V2 V3 V4
# 363  0  1  1  0
# 202  1  0  0  1
# 228  0  1  0  0
# 890  1  0  1  1
# 306  0  1  0  0
# 69   0  0  1  1
# 810  0  0  1  1
# 293  1  0  1  0

如果您得到的向量中少于少于100,我会进行max(...)。如果没有max,您可能会看到cannot take a sample larger than the population when 'replace = FALSE'

答案 1 :(得分:1)

如果您的数据是数字,则坚持使用矩阵,不要将其强制转换为数据框。转换类型会产生计算成本,在这种情况下,数据框不会提供任何明显的优势。使用一些略有不同的数据:

set.seed(12345)
my.matrix <- matrix(sample(c(sample.int(12000, 90000, T), rep(0, 10000))),
                    ncol = 100,
                    nrow = 1000
                    )

获取由my.matrix != 0创建的逻辑矩阵的行总和,对于非零值则为TRUE。然后设置您的上限和下限阈值,在which中进行比较,以获取包含至少x和最多y个非零值的所有行的索引,并绘制一个样本从那开始,n = 100,并使用得到的索引来子集您的数据框:

rs <- rowSums(my.matrix != 0)

x <- 85 # lower threshold
y <- 90 # upper threshold

my.matrix[sample(which(rs >= x & rs <= y), 100),]