基于微型和行中的最大非零元素对数据框进行亚采样

  • 本文关键字:数据 元素 采样 于微型 r
  • 更新时间 :
  • 英文 :


我的计数矩阵具有许多零元素:

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

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

我想随机选择至少x n的n行(n = 100,例如(,但不超过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

该怎么做?预先感谢您!

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

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

我做了max(...),以防您在生成的向量中少于100的。没有max,您可能会看到cannot take a sample larger than the population when 'replace = FALSE'

如果您的数据是数字的,则使用矩阵粘上,并且不要将其逼入数据框架。转换类型的计算成本,在这种情况下,数据框架没有任何明显的优势。使用一些略有不同的数据:

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

获取由my.matrix != 0创建的逻辑矩阵的行总和,对于非零值是正确的。然后设置上下阈值,在which中进行比较,以获取所有至少包含x和最多y的行的索引子集您的数据框:

rs <- rowSums(my.matrix != 0)
x <- 85 # lower threshold
y <- 90 # upper threshold
my.matrix[sample(which(rs >= x & rs <= y), 100),]

最新更新