首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R-使用迭代器和iterpc包;我可以创建迭代器的子集吗?

R-使用迭代器和iterpc包;我可以创建迭代器的子集吗?
EN

Stack Overflow用户
提问于 2016-04-05 00:28:27
回答 1查看 361关注 0票数 0

我使用iterpc创建了一个迭代器,然后将其包装在iterators::iter包中。

代码语言:javascript
复制
iter<-iterpc(nrow(data),4,ordered=TRUE,replace=TRUE)
it<-iter_wrapper(iter)

然后,我使用foreach进行计算。

代码语言:javascript
复制
calcs<-foreach(i=it)%dopar%{
    blah}

我的问题是我不想使用迭代器中的每一个元素。我想随机选择迭代器的某些元素,比如1000个。(计算时间是个问题)如何选择迭代器的随机子集?

EN

回答 1

Stack Overflow用户

发布于 2016-04-05 01:20:06

我怀疑排列迭代器是按顺序工作的,所以无法随机采样。您可以做的是编写一个迭代器,该迭代器在父迭代器上重复调用nextElem以返回精简版本。这个例子通过一些“瘦”参数创建了一个迭代器的精简版本:

代码语言:javascript
复制
 > thinit = function(iterator,thin){
   iter(
        function(){
            for(i in 1:(thin-1)){
               nextElem(iterator)
            }
            nextElem(iterator)}
        )
   }

注意,我在循环中调用了thin-1次,所以最后一次调用是迭代器返回值。

因此,从一个简单的1:100迭代器开始:

代码语言:javascript
复制
 > i1 <- iter(1:100)

制作一个精简版本:

代码语言:javascript
复制
 > i10 = thinit(i1, 10)

然后对循环输出进行精简:

代码语言:javascript
复制
 > foreach(i=i10) %dopar% {i}
[[1]]
[1] 10

[[2]]
[1] 20

[[3]]
[1] 30

现在,您可以让包装器随机调用nextElem多次(只要它返回nextElem调用,它就会作为迭代器工作),以便从父迭代器中随机获取样本。你不可能从排列中准确地得到250个样本,但是如果你知道有2500个排列,你调用nextElem直到runif(1)>.9,你平均会得到250个……或者别的什么。如下所示:

代码语言:javascript
复制
> pthin = function(iterator, p){
   iter(
     function(){
       while(runif(1)<p){
         nextElem(iterator)
         }
       nextElem(iterator)
      }
    )
   }
> i1 <- iter(1:100)
> ip10 = pthin(i1,.9)
> unlist(foreach(i=ip10) %dopar% {i})
 [1]  1  9 18 19 22 28 35 38 53 55 63 67 81 84 86 89 95 98
> i1 <- iter(1:100)
> ip10 = pthin(i1,.9)
> unlist(foreach(i=ip10) %dopar% {i})
 [1]  15  19  21  24  45  59  63  70  73  76  79  88  94 100
> i1 <- iter(1:100)
> ip10 = pthin(i1,.9)
> unlist(foreach(i=ip10) %dopar% {i})
[1] 10 50 62 76 79 81 97

请注意,父迭代器被调用了大N次,但采样意味着{i}中的循环中的肉只被调用了很少的次数,我怀疑这是花费了大部分时间的地方。

如果您确实坚持从父迭代器中获取给定的N个样本,并且您知道迭代器中元素的数量,那么可以从该迭代器中计算N个样本,并使用如上所述的迭代器包装器,该包装器会一直在父迭代器上调用nextElem,直到它到达样本中的下一个索引,然后返回该值。它必须保持闭包中返回哪些样本的状态,就像我的示例一样。目前还不能完全做到这一点(需要更多的咖啡),所以这里有一个替代方法:

创建一个迭代器包装器,它返回一个迭代器,该迭代器生成原始迭代器的值以及从1到N的连续索引号。这类似于python zip函数。然后只在索引号在子集中的那些迭代上工作。应该知道原始迭代器的长度才能生成子集。示例:

这是我的zip迭代器包装器。它返回一个迭代器,用于生成列表元素,其中$index是连续的索引,$value是来自父迭代器的值:

代码语言:javascript
复制
> zipit = function(iz){
    itn=1
    iter(
       function(){
          itn<<-itn+1
          list(index=itn-1,value=nextElem(iz))
          }
        )
     }

现在,根据需要创建一个置换迭代器。我们知道这个元素总共有10个元素,所以从10个元素中生成一个包含4个值的样本:

代码语言:javascript
复制
> I <- iterpc(5, 2)
> it <- iter_wrapper(I)
> subset = sample(10,4)

现在,您的主循环有了一个测试,并且只处理(在本例中是值的简单和)子集中的那些迭代:

代码语言:javascript
复制
> foreach(i=zipit(it), .combine=c) %do% {if(i$index %in% subset)sum(i$value)}
[1] 4 7 8 9
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36408016

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档