Hi. I have the following code in a loop. It splits a vector into subvectors of equal size. But if the size of the original vector is not an exact multiple of the desired subvector size, then the first few subvectors have one more element than the last few. I know that the cut function could be used to determine where to break up the vector, but it doesn't seem to provide control over where to put the larger and smaller subvectors. numgp1_v=sidect_v%/%compmin numgroup_v[small]=max(1,numgp1_v[small]) sidemin_v=sidect_v%/%numgroup_v nummax_v=sidect_v%%sidemin_v eix=0 smallindexlist<-list(NULL) for(i in 1:numgroup_v[small]) { bix=eix+1 eix=bix+sidemin_v[small]+(i<=nummax_v[small])-1 smallindexlist[[i]]<-dlpo_sm_v[bix:eix] } The key fact is that smallindexlist is a list, each list element is a subvector of dlpo_sm_v of the proper size. The sizes may be different. I tried to see whether I could eliminate the loop, as follows. First I defined a function: intgpi <- function(totalength,numgroups,groupnum,place="LEFT") { # function to split the integer sequence, 1:totalength, into the groupnum group out of numgroups groups of equal size, totalength%/%numgroups # there are totalength%%numgroups number of groups of length 1+totalength%/%numgroups, with the large groups all to one side, left if place=LEFT # totalength >= numgroups >= groupnum all integers, or it won't work right if(charmatch(toupper(place),"RIGHT",nomatch=FALSE)==1){ extra1_1=max((groupnum-1)+((totalength%%numgroups)-numgroups),0) extra1_2=(groupnum>numgroups-totalength%%numgroups) } else{ extra1_1=min(totalength%%numgroups,groupnum-1) extra1_2=(groupnum<=totalength%%numgroups) } gsize=totalength%/%numgroups gleft=((groupnum-1)*gsize)+extra1_1+1 gright=gleft+gsize+extra1_2-1 gleft:gright } The function appears to work okay. Then I used it as follows: numgp1_v=sidect_v%/%compmin numgroup_v[small]=max(1,numgp1_v[small]) smallindexlist<-list(NULL) smallindexlist=sapply(1:numgroup_v[small],function(i){dlpo_sm_v[intgpi(sidect_v[small],numgroup_v[small],i)]}) In this case, smallindexlist will be a list like I had before if the subvectors are not all the same size, but if the subvectors are all the same size, it appears that I get an array. Can I force this operation to give me a list the way I want it in all cases? Or is there a better way to deloop my original code? Thanks! -- TMK -- 212-460-5430 home 917-656-5351 cell
This might do what you want:> # test data > x <- 1:43 > nb <- 5 # number of subsets > # create vector of lengths of subsets > ns <- rep(length(x) %/% nb, nb) > # see if we have to adjust counts of initial subsets > if ((.offset <- length(x) %% nb) != 0) ns[1:.offset] = ns[1:.offset] + 1 > # create the subsets > split(x, rep(1:nb,ns))$`1` [1] 1 2 3 4 5 6 7 8 9 $`2` [1] 10 11 12 13 14 15 16 17 18 $`3` [1] 19 20 21 22 23 24 25 26 27 $`4` [1] 28 29 30 31 32 33 34 35 $`5` [1] 36 37 38 39 40 41 42 43 On 2/1/07, Talbot Katz <topkatz at msn.com> wrote:> Hi. > > I have the following code in a loop. It splits a vector into subvectors of > equal size. But if the size of the original vector is not an exact multiple > of the desired subvector size, then the first few subvectors have one more > element than the last few. I know that the cut function could be used to > determine where to break up the vector, but it doesn't seem to provide > control over where to put the larger and smaller subvectors. > > numgp1_v=sidect_v%/%compmin > numgroup_v[small]=max(1,numgp1_v[small]) > sidemin_v=sidect_v%/%numgroup_v > nummax_v=sidect_v%%sidemin_v > eix=0 > smallindexlist<-list(NULL) > for(i in 1:numgroup_v[small]) { > bix=eix+1 > eix=bix+sidemin_v[small]+(i<=nummax_v[small])-1 > smallindexlist[[i]]<-dlpo_sm_v[bix:eix] > } > > The key fact is that smallindexlist is a list, each list element is a > subvector of dlpo_sm_v of the proper size. The sizes may be different. > > > I tried to see whether I could eliminate the loop, as follows. First I > defined a function: > > intgpi <- function(totalength,numgroups,groupnum,place="LEFT") { > # function to split the integer sequence, 1:totalength, into the groupnum > group out of numgroups groups of equal size, totalength%/%numgroups > # there are totalength%%numgroups number of groups of length > 1+totalength%/%numgroups, with the large groups all to one side, left if > place=LEFT > # totalength >= numgroups >= groupnum all integers, or it won't work right > if(charmatch(toupper(place),"RIGHT",nomatch=FALSE)==1){ > extra1_1=max((groupnum-1)+((totalength%%numgroups)-numgroups),0) > extra1_2=(groupnum>numgroups-totalength%%numgroups) > } > else{ > extra1_1=min(totalength%%numgroups,groupnum-1) > extra1_2=(groupnum<=totalength%%numgroups) > } > gsize=totalength%/%numgroups > gleft=((groupnum-1)*gsize)+extra1_1+1 > gright=gleft+gsize+extra1_2-1 > gleft:gright > } > > > The function appears to work okay. Then I used it as follows: > > numgp1_v=sidect_v%/%compmin > numgroup_v[small]=max(1,numgp1_v[small]) > smallindexlist<-list(NULL) > smallindexlist=sapply(1:numgroup_v[small],function(i){dlpo_sm_v[intgpi(sidect_v[small],numgroup_v[small],i)]}) > > In this case, smallindexlist will be a list like I had before if the > subvectors are not all the same size, but if the subvectors are all the same > size, it appears that I get an array. Can I force this operation to give me > a list the way I want it in all cases? Or is there a better way to deloop > my original code? > > Thanks! > > -- TMK -- > 212-460-5430 home > 917-656-5351 cell > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >-- Jim Holtman Cincinnati, OH +1 513 646 9390 What is the problem you are trying to solve?
Consider na=43; nb=5; x=1:na ns=rep(na %/% nb, nb) + (1:nb <= na %% nb) split(x, rep(1:nb, ns)) Heikki Kaskelma On Fri, 2 Feb 2007, jim holtman <jholtman at gmail.com> wrote:>This might do what you want: > > # test data > x <- 1:43 > nb <- 5 # number of subsets > # create vector of lengths of subsets > ns <- rep(length(x) %/% nb, nb) > # see if we have to adjust counts of initial subsets > if ((.offset <- length(x) %% nb) != 0) ns[1:.offset] = ns[1:.offset] +1> # create the subsets > split(x, rep(1:nb,ns))
Jim and Heikki, Thank you so much for your inventive solutions, much better and more efficient than my approach! As a footnote to my original post, it turns out that using lapply rather than sapply consistently returns a list, and not an array (which sapply gives when the number of points is an exact multiple of the number of groups). -- TMK -- 212-460-5430 home 917-656-5351 cell>From: "Kaskelma, Heikki" <kashei at sip-oy.com> >To: "jim holtman" <jholtman at gmail.com>,"Talbot Katz" <topkatz at msn.com> >CC: <r-help at stat.math.ethz.ch> >Subject: RE: [R] Can this loop be delooped? >Date: Fri, 2 Feb 2007 16:06:51 +0200 > >Consider > >na=43; nb=5; x=1:na >ns=rep(na %/% nb, nb) + (1:nb <= na %% nb) >split(x, rep(1:nb, ns)) > > >Heikki Kaskelma > >On Fri, 2 Feb 2007, jim holtman <jholtman at gmail.com> wrote: > >This might do what you want: > > > > # test data > > x <- 1:43 > > nb <- 5 # number of subsets > > # create vector of lengths of subsets > > ns <- rep(length(x) %/% nb, nb) > > # see if we have to adjust counts of initial subsets > > if ((.offset <- length(x) %% nb) != 0) ns[1:.offset] = ns[1:.offset] + >1 > > # create the subsets > > split(x, rep(1:nb,ns))
Reasonably Related Threads
- ggplot: Problem with legend background
- Directory metadata inconsistencies and missing output ("mismatched layout" and "no dentry for inode" error)
- frailtypack
- [Bug 871] New: Running two instances of ulog causes abort in libnfnetlink
- Another loop - deloop question