3

I have a vector of binary variables which state whether a product is on promotion in the period. I'm trying to work out how to calculate the duration of each promotion and the duration between promotions.

promo.flag = c(1,1,0,1,0,0,1,1,1,0,1,1,0))

So in other words: if promo.flag is same as previous period then running.total + 1, else running.total is reset to 1

I've tried playing with apply functions and cumsum but can't manage to get the conditional reset of running total working :-(

The output I need is:

promo.flag =  c(1,1,0,1,0,0,1,1,1,0,1,1,0)
rolling.sum = c(1,2,1,1,1,2,1,2,3,1,1,2,0)

Can anybody shed any light on how to achieve this in R?

Adi Lester
  • 24,731
  • 12
  • 95
  • 110
Matt Weller
  • 2,684
  • 2
  • 21
  • 30

1 Answers1

4

It sounds like you need run length encoding (via the rle command in base R).

unlist(sapply(rle(promo.flag)$lengths,seq))

Gives you a vector 1 2 1 1 1 2 1 2 3 1 1 2 1. Not sure what you're going for with the zero at the end, but I assume it's a terminal condition and easy to change after the fact.

This works because rle() returns a list of two, one of which is named lengths and contains a compact sequence of how many times each is repeated. Then seq when fed a single integer gives you a sequence from 1 to that number. Then apply repeatedly calls seq with the single numbers in rle()$lengths, generating a list of the mini sequences. unlist then turns that list into a vector.

Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235
  • Many thanks, that's fixed it and given me further functions to learn!! Excellent, prompt response! – Matt Weller Feb 13 '12 at 01:13
  • No problem. As it turns out, I just found a use for this very function :-). Also take a look at the `rollapply` family of functions in the `zoo` library, which are more powerful but at the price of a fixed window size (there may be a way to change it; I'm not super familiar with them). – Ari B. Friedman Feb 13 '12 at 01:25
  • P.S. Welcome to Stack Overflow! We hope you'll stick around the [r] tag. – Ari B. Friedman Feb 13 '12 at 01:26