I have the following function count.ones
that takes in a data frame data.l
in which the observations have been subdivided into bins defined by indices, a vector of consecutive indices x
, and the length of the sliding window width
over consecutive indices. The goal of this function is to slide over the indices and count the number of observations labeled as ones.
count.ones = function(x,data.l,width){
labvec = data.l$lab
indvec = data.l$index
return(sapply(1:(length(x)-(width-1)),
function(j) sum(labvec[indvec%in%x[j:(j+(width-1))]])))
}
My data is as follows:
library(ks)
library(zoo)
library(plyr)
library(BBmisc)
library(ggplot2)
library(rje)
set.seed(1234)
n1 = n2 = 50000
X1 = rnorm.mixt(n=n1,mus=c(0.4,0.8),sigmas=c(0.04,0.04),props=c(0.97,0.03))
X2 = rnorm.mixt(n=n2,mus=c(0.4,0.8),sigmas=c(0.04,0.04),props=c(0.98,0.02))
n1 = length(X1)
n2 = length(X2)
#pooled observations - label X1's as 1 and X2's as 0
dat = data.frame(X=c(X1,X2),lab=c(rep(1,n1),rep(0,n2)))
N = n1+n2
#number in each bin
n = N^(1/3)
dat$quant = with(dat, cut_number(dat$X, n = round(N/n)))
#number of bins
M = length(levels(dat$quant))
dat$index = factor(dat$quant, levels = levels(dat$quant),
labels = 1:length(levels(dat$quant)))
Example function call:
indx.contig = seq(M)
count.ones(x=indx.contig,data.l=dat,width=1) #can vary width for any integer >= 1
This function seems to be slower than expected as it's only performing the simple task of counting the number of 1's in each sliding window. This would become problematic as n1
and n2
increase into the millions (which is ultimately what I want to use). Is there a way to speed this up? I initially looked into rollapply
in the zoo
package, but it is not as flexible as my code.
It is important for me to look at consecutive indices. If, for example, I had:
indx.vec = c(1:10,14:20)
I would first create a list with two elements: one containing 1:10
and the other containing 14:20
. I would then run count.ones
on each of the elements using sapply
.