Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 具有固定列和的随机二进制数据帧_R_Loops_Random_Binary - Fatal编程技术网

R 具有固定列和的随机二进制数据帧

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

我试图构建一个完全由1和0组成的数据帧。它应该是随机构建的,除了每个列需要相加到一个指定的值


如果只针对一个数据帧,我会知道如何做到这一点,但它需要构建到一个函数中,在所述函数中,它将作为一个迭代过程完成,最高可达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.5
1s
<代码>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