# [R] Breakdown a number

Paul Roebuck roebuck at mdanderson.org
Thu Apr 20 11:27:07 CEST 2006

```On Thu, 20 Apr 2006, Gabor Grothendieck wrote:

> On 4/19/06, Paul Roebuck <roebuck at mdanderson.org> wrote:
> > On Wed, 19 Apr 2006, Gabor Grothendieck wrote:
> >
> > > On 4/19/06, Paul Roebuck <roebuck at mdanderson.org> wrote:
> > >
> > > > Isn't there a builtin method for doing this and, if so,
> > > > what is it called?
> > > >
> > > >        breakdown <- function(whole) {
> > > >            breaks <- c(250, 800)
> > > >            pieces <- integer(length(breaks) + 1)
> > > >            if (whole > breaks[2]) {
> > > >                pieces[3] <- whole - breaks[2]
> > > >                whole <- breaks[2]
> > > >            }
> > > >            if (whole > breaks[1]) {
> > > >                pieces[2] <- whole - breaks[1]
> > > >                whole <- breaks[1]
> > > >            }
> > > >            pieces[1] <- whole
> > > >
> > > >            return(pieces)
> > > >        }
> > > >
> > > > breakdown(1200) # 250 550 400
> > >
> > > Maybe you could discuss in words what you want but perhaps
> > > you are looking for diff:
> >
> > That was rather my problem searching for my answer as I
> > was unsure what this was called. I was searching for
> > 'bins' or 'breaks' (like in hist method but not for
> > plotting) and leading nowhere fast. Alas, I thought
> > sample code would go further than my description.
> >
> >
> > > > bp <- c(0, 250, 800, 1200)
> > > > diff(bp)
> > > [1] 250 550 400
> >
> > Don't think diff method is going to work either, at
> > least in cases where the 'whole' is less than greatest
> > 'break'.
> >
> > > breakdown2 <- function(x, breaks = c(250, 800)) {
> >      diff(c(0, breaks, x))
> >  }
> > > breakdown(10)         # 10 0 0
> > > breakdown2(10)        # 250 550 -790
> > >
> > > breakdown(400)        # 250 150 0
> > > breakdown2(400)       # 250 550 -400
> >
>
> Just sort it:
>
> bd <- function(x, breaks = c(250, 800)) diff(sort(c(0, breaks, x)))

Doesn't work either. Tests below didn't fare well.

> If you don't want the 0 values in the case that x is one of the
> breaks then use diff(sort(unique(c(0, breaks, x))))

I did want the zeros in the result.

###
check.results <- function(input) {
stopifnot(input >= 0)
output <- bd(input)
expected <- breakdown(input)
if (!identical(output, expected)) {
cat("expected:", expected, "\n")
cat("output:  ", output,   "\n")
return(FALSE)
} else {
return(TRUE)
}
}

check.results(1200)	# TRUE
check.results(800)	# TRUE
check.results(799)	# FALSE
check.results(500)	# FALSE
check.results(250)      # FALSE
check.results(200)	# FALSE
check.results(1)	# FALSE
check.results(0)	# FALSE

Goal was to split value according to breaks such that each
piece of it could later be multiplied with a corresponding
rate. It's not unlike the type of processing that would go
into figuring out how much a hypothetical out-of-state phone
call would cost (for example, .10 for first five minutes,
0.07 for next ten minutes, and 0.05 for rest of the call)

calc.cost.per.call <- function(minutes) {
duration <- bd(minutes, breaks = c(5, 10))
rates <- c(0.10, 0.07, 0.05)
sum(duration * rates)
}

calc.cost.per.call(24)	# would be 1.65

Thanks for your help.

----------------------------------------------------------
SIGSIG -- signature too long (core dumped)

```