我有一个包含许多零元素的计数矩阵:
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
该怎么做? 预先谢谢你!
答案 0 :(得分:2)
为可复制的随机数据设置种子:
set.seed(2)
my.matrix <- as.data.frame(matrix(rbinom(100 * 1000, 1, 0.5), ncol = 100, nrow = 1000))
apply
和rowSums
之类的功能会将数据转换为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::between
或data.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),]