R 具有固定列和的随机二进制数据帧
我试图构建一个完全由1和0组成的数据帧。它应该是随机构建的,除了每个列需要相加到一个指定的值R 具有固定列和的随机二进制数据帧,r,loops,random,binary,R,Loops,Random,Binary,我试图构建一个完全由1和0组成的数据帧。它应该是随机构建的,除了每个列需要相加到一个指定的值 如果只针对一个数据帧,我会知道如何做到这一点,但它需要构建到一个函数中,在所述函数中,它将作为一个迭代过程完成,最高可达1000倍 一种有效的方法是为每列洗牌一个向量,使其具有适当数量的1和0。您可以定义以下函数来生成具有指定行数和每列1数的矩阵: build.mat <- function(nrow, csums) { sapply(csums, function(x) sample(rep
如果只针对一个数据帧,我会知道如何做到这一点,但它需要构建到一个函数中,在所述函数中,它将作为一个迭代过程完成,最高可达1000倍 一种有效的方法是为每列洗牌一个向量,使其具有适当数量的1和0。您可以定义以下函数来生成具有指定行数和每列1数的矩阵:
build.mat <- function(nrow, csums) {
sapply(csums, function(x) sample(rep(c(0, 1), c(nrow-x, x))))
}
set.seed(144)
build.mat(5, 0:5)
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 0 0 0 0 1 1
# [2,] 0 0 0 1 0 1
# [3,] 0 0 0 0 1 1
# [4,] 0 1 1 1 1 1
# [5,] 0 0 1 1 1 1
如果零比一多得多,反之亦然,@akrun的方法可能更快:
build_01_mat <- function(n,n1s){
nc <- length(n1s)
zerofirst <- sum(n1s) < n*nc/2
tochange <- if (zerofirst) n1s else n-n1s
mat <- matrix(if (zerofirst) 0L else 1L,n,nc)
mat[cbind(
unlist(c(sapply((1:nc)[tochange>0],function(col)sample(1:n,tochange[col])))),
rep(1:nc,tochange)
)] <- if (zerofirst) 1L else 0L
mat
}
set.seed(1)
build_01_mat(5,c(1,3,0))
# [,1] [,2] [,3]
# [1,] 0 0 0
# [2,] 1 1 0
# [3,] 0 1 0
# [4,] 0 1 0
# [5,] 0 0 0
如果可以对一个数据帧执行此操作,请编写相应的函数,然后将其放入
for
循环或在其上运行replicate
。你需要更加具体,展示你所做的尝试,并展示示例输入和期望的输出,这才是一个好问题。你可以使用sample
。例如,假设您要创建一个长度为10、总和为5的向量。i、 e.51s
<代码>v1我想两个答案都没有明确说明,但在这里使用矩阵而不是data.frame是至关重要的。顺便说一下,有一个“性能”标签,你可以考虑添加到这个问题,如果它是你的首要关注。不知道为什么这几乎是封闭的,如不清楚。乔西尔伯和我似乎同意对它的解释……是的,我认为这是正确的方式,尽管我不会使用nrow
(因为它是一个函数名)。此外,OP声称必须多次执行此操作,因此如果这些运行中的行数很小且恒定,则可以在函数外部预计算并存储向量,以便更快地访问:vecs@Frank good catch--我删除了对nrow
的覆盖。我想,如果你的提案加快了速度,可能会有一些用例,但对于长而窄的数据帧,它可能会使代码慢得多,因为你需要分配一个巨大的矩阵vecs
,其中大部分你可能永远不会使用;我想这取决于情况,阿克伦的方法是否更快。(补充了一个解释。)嗯,我想你可以更进一步,也可以用一个if语句来检测是否有更多的1或0,然后决定是从所有0开始并替换少数1,还是从所有1开始并替换少数0。@josilber好的,我已经做出了改变。基准测试与直觉非常吻合。在“替换”方法速度达到2倍之前,您必须进行大约75-25次拆分。我相信这两种方法都可以加快一些速度,所以我可能仍然会选择“置换”方法,除非我的数据是超级不平衡的。
build_01_mat <- function(n,n1s){
nc <- length(n1s)
zerofirst <- sum(n1s) < n*nc/2
tochange <- if (zerofirst) n1s else n-n1s
mat <- matrix(if (zerofirst) 0L else 1L,n,nc)
mat[cbind(
unlist(c(sapply((1:nc)[tochange>0],function(col)sample(1:n,tochange[col])))),
rep(1:nc,tochange)
)] <- if (zerofirst) 1L else 0L
mat
}
set.seed(1)
build_01_mat(5,c(1,3,0))
# [,1] [,2] [,3]
# [1,] 0 0 0
# [2,] 1 1 0
# [3,] 0 1 0
# [4,] 0 1 0
# [5,] 0 0 0
require(rbenchmark)
# similar numbers of zeros and ones
benchmark(
permute=build.mat(1e7,1e7/2),
replace=build_01_mat(1e7,1e7/2),replications=10)[1:5]
# test replications elapsed relative user.self
# 1 permute 10 7.68 1.126 6.59
# 2 replace 10 6.82 1.000 6.27
# many more zeros than ones
benchmark(
permute=build.mat(1e6,rep(10,20)),
replace=build_01_mat(1e6,rep(10,20)),replications=10)[1:5]
# test replications elapsed relative user.self
# 1 permute 10 10.28 3.779 8.51
# 2 replace 10 2.72 1.000 2.23
# many more ones than zeros
benchmark(
permute=build.mat(1e6,1e6-rep(10,20)),
replace=build_01_mat(1e6,1e6-rep(10,20)),replications=10)[1:5]
# test replications elapsed relative user.self
# 1 permute 10 10.94 4.341 9.28
# 2 replace 10 2.52 1.000 2.09