I am trying to set up a function which processes my data according to the following rules: 1. if (x[i]==0) NA 2. if (x[i]>0) log(x[i]/(number of consecutive zeros immediately preceding it +1)) The data this will apply to include a variety of whole numbers not limited to 1 & 0, a number of which may appear consecutively and not separated by zeros. Below is an example with a detailed explanation of the output desired: x <- c(3,2,0,1,0,2,0,0,1,0,0,0,0,4,1) output desired = c(1.098, 0.69, NA, -0.69, NA, -0.41, NA, NA, 1.098, NA, NA, NA, NA, -0.22, 0) the 1st element, 3, becomes log(3) = 1.098612 the 2nd element, 2, becomes log(2) = 0.6931472 the 3rd element, 0, becomes NA (cannot log zero). the 4rd element, 1, becomes log(1/(1(number of consecutive zeros immediately preceding it) + 1 (constant))) = log(1/2) = -0.6931472 the 5th element, 0, becomes NA the 6th element, 2, becomes log(2/(1(number of consecutive zeros immediately preceding it) + 1 (constant))) = log(2/3) = -0.4054651 the 7th and 8th elements, both zeros, become NA the 9th element, 1, becomes log(1/(2(number of consecutive zeros immediately preceding it) + 1 (constant))) = log(1/3) = 1.098612 the 10-13th elements, all zeros, each become NA the 14th element, 4, becomes log(4/(4(number of consecutive zeros immediately preceding it) + 1 (constant))) = log(4/5) = -0.2231436 the 15th element, 1, becomes log(1) = 0 This one has been in the works for some time and I can't quite seem to crack it. I would be indebted to anyone who could with success - it seemed so simple at the offset! Tyler -- View this message in context: http://www.nabble.com/NOT-SO-SIMPLE-function%21-tp17607348p17607348.html Sent from the R help mailing list archive at Nabble.com.
on 06/02/2008 01:30 PM T.D.Rudolph wrote:> I am trying to set up a function which processes my data according to the > following rules: > > 1. if (x[i]==0) NA > 2. if (x[i]>0) log(x[i]/(number of consecutive zeros immediately preceding > it +1)) > > The data this will apply to include a variety of whole numbers not limited > to 1 & 0, a number of which may appear consecutively and not separated by > zeros. Below is an example with a detailed explanation of the output > desired: > > x <- c(3,2,0,1,0,2,0,0,1,0,0,0,0,4,1) > output desired = c(1.098, 0.69, NA, -0.69, NA, -0.41, NA, NA, 1.098, NA, NA, > NA, NA, -0.22, 0) > > the 1st element, 3, becomes log(3) = 1.098612 > the 2nd element, 2, becomes log(2) = 0.6931472 > the 3rd element, 0, becomes NA (cannot log zero). > the 4rd element, 1, becomes log(1/(1(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(1/2) = -0.6931472 > the 5th element, 0, becomes NA > the 6th element, 2, becomes log(2/(1(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(2/3) = -0.4054651The above should be log(2/2) = 0 There is only 1 consecutive zero preceding the 2 in the 6th position> the 7th and 8th elements, both zeros, become NA > the 9th element, 1, becomes log(1/(2(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(1/3) = 1.098612The above should be log(1/3) = -1.098612 (negative, not positive)> the 10-13th elements, all zeros, each become NA > the 14th element, 4, becomes log(4/(4(number of consecutive zeros > immediately preceding it) + 1 (constant))) = log(4/5) = -0.2231436 > the 15th element, 1, becomes log(1) = 0 > > This one has been in the works for some time and I can't quite seem to crack > it. > I would be indebted to anyone who could with success - it seemed so simple > at the offset! > TylerI am presuming that you have some typos/errors above in your per element explanation of the processing of the vector. If so, then the following should work as a first pass and could probably be optimized further: zeroes <- function(x, i) { if (x[i] == 0) { NA } else if (i == 1) { log(x[i]) } else if (x[i - 1] != 0) { log(x[i]) } else { rz <- rle(x[1:(i-1)]) log(x[i] / (rz$lengths[length(rz$lengths)] + 1)) } } x <- c(3, 2, 0, 1, 0, 2, 0, 0, 1, 0, 0, 0, 0, 4, 1) > sapply(seq(along = x), function(i) zeroes(x, i)) [1] 1.0986123 0.6931472 NA -0.6931472 NA 0.0000000 [7] NA NA -1.0986123 NA NA NA [13] NA -0.2231436 0.0000000 See ?rle for more information on the identification of the sequential zeroes in the vector. HTH, Marc Schwartz
You are absolutely correct Marc; thank you for making this assumption! While it will take some time for me to rightfully understand the logical ordering of your proposed function, it certainly seems to produce the result I was looking for, and economically at that. rle is indeed highly useful in this context! Cheers Tyler -- View this message in context: http://www.nabble.com/NOT-SO-SIMPLE-function%21-tp17607348p17610783.html Sent from the R help mailing list archive at Nabble.com.
In the following cs increases by 1 for each nonzero entry in x. Thus the zeros plus the preceding nonzero form runs in cs. seq(cs)-match(cs,cs) assigns 0 to the first element of each such run, 1 to the next, 2 to the next and so on. Thus shifting it forward and adding 1 gives the number of preceding zeros, num0p1. cs <- cumsum(x != 0) num0p1 <- head(c(0, seq(cs) - match(cs, cs)), -1) + 1 ifelse(x == 0, NA, log(x/num0p1)) On Mon, Jun 2, 2008 at 2:30 PM, T.D.Rudolph <prairie.picker at gmail.com> wrote:> > I am trying to set up a function which processes my data according to the > following rules: > > 1. if (x[i]==0) NA > 2. if (x[i]>0) log(x[i]/(number of consecutive zeros immediately preceding > it +1)) > > The data this will apply to include a variety of whole numbers not limited > to 1 & 0, a number of which may appear consecutively and not separated by > zeros. Below is an example with a detailed explanation of the output > desired: > > x <- c(3,2,0,1,0,2,0,0,1,0,0,0,0,4,1) > output desired = c(1.098, 0.69, NA, -0.69, NA, -0.41, NA, NA, 1.098, NA, NA, > NA, NA, -0.22, 0) > > the 1st element, 3, becomes log(3) = 1.098612 > the 2nd element, 2, becomes log(2) = 0.6931472 > the 3rd element, 0, becomes NA (cannot log zero). > the 4rd element, 1, becomes log(1/(1(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(1/2) = -0.6931472 > the 5th element, 0, becomes NA > the 6th element, 2, becomes log(2/(1(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(2/3) = -0.4054651 > the 7th and 8th elements, both zeros, become NA > the 9th element, 1, becomes log(1/(2(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(1/3) = 1.098612 > the 10-13th elements, all zeros, each become NA > the 14th element, 4, becomes log(4/(4(number of consecutive zeros > immediately preceding it) + 1 (constant))) = log(4/5) = -0.2231436 > the 15th element, 1, becomes log(1) = 0 > > This one has been in the works for some time and I can't quite seem to crack > it. > I would be indebted to anyone who could with success - it seemed so simple > at the offset! > Tyler > -- > View this message in context: http://www.nabble.com/NOT-SO-SIMPLE-function%21-tp17607348p17607348.html > Sent from the R help mailing list archive at Nabble.com. > > ______________________________________________ > R-help at r-project.org 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. >
In the following cs increases by 1 for each nonzero entry in x. Thus the zeros plus the preceding nonzero form runs in cs. seq(cs)-match(cs,cs) assigns 0 to the first element of each such run, 1 to the next, 2 to the next and so on. Thus shifting it forward and adding 1 gives the number of preceding zeros, num0p1. cs <- cumsum(x != 0) num0p1 <- head(c(0, seq(cs) - match(cs, cs)), -1) + 1 ifelse(x == 0, NA, log(x/num0p1)) On Mon, Jun 2, 2008 at 2:30 PM, T.D.Rudolph <prairie.picker at gmail.com> wrote:> > I am trying to set up a function which processes my data according to the > following rules: > > 1. if (x[i]==0) NA > 2. if (x[i]>0) log(x[i]/(number of consecutive zeros immediately preceding > it +1)) > > The data this will apply to include a variety of whole numbers not limited > to 1 & 0, a number of which may appear consecutively and not separated by > zeros. Below is an example with a detailed explanation of the output > desired: > > x <- c(3,2,0,1,0,2,0,0,1,0,0,0,0,4,1) > output desired = c(1.098, 0.69, NA, -0.69, NA, -0.41, NA, NA, 1.098, NA, NA, > NA, NA, -0.22, 0) > > the 1st element, 3, becomes log(3) = 1.098612 > the 2nd element, 2, becomes log(2) = 0.6931472 > the 3rd element, 0, becomes NA (cannot log zero). > the 4rd element, 1, becomes log(1/(1(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(1/2) = -0.6931472 > the 5th element, 0, becomes NA > the 6th element, 2, becomes log(2/(1(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(2/3) = -0.4054651 > the 7th and 8th elements, both zeros, become NA > the 9th element, 1, becomes log(1/(2(number of consecutive zeros immediately > preceding it) + 1 (constant))) = log(1/3) = 1.098612 > the 10-13th elements, all zeros, each become NA > the 14th element, 4, becomes log(4/(4(number of consecutive zeros > immediately preceding it) + 1 (constant))) = log(4/5) = -0.2231436 > the 15th element, 1, becomes log(1) = 0 > > This one has been in the works for some time and I can't quite seem to crack > it. > I would be indebted to anyone who could with success - it seemed so simple > at the offset! > Tyler > -- > View this message in context: http://www.nabble.com/NOT-SO-SIMPLE-function%21-tp17607348p17607348.html > Sent from the R help mailing list archive at Nabble.com. > > ______________________________________________ > R-help at r-project.org 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. >