Take the 2-minute tour ×

This is not a complicated problem, and I have a solution, but I can't shake the feeling that there is a better way:

I have a data.frame with a tally of successes and opportunities by category, like this:

testFrame <- data.frame(successes = c(100, 150, 18),
                        opportunities = c(215, 194, 40),
                        category = LETTERS[1:3])
testFrame$category <- as.character(testFrame$category)

I want to convert this to a "tall" data.frame, with one column of 1s and 0s indicating success/failure and a second with category labels. I can do this with the following code:

tallFrame <- lapply(1:nrow(testFrame), function(rr){
  cbind(rep(c(1, 0), c(testFrame[rr, "successes"], testFrame[rr, "opportunities"]-testFrame[rr, "successes"])), testFrame[rr, "category"])
tallFrame <- data.frame(do.call(rbind, tallFrame))

The resulting tallFrame is a matrix which I can then convert to a data.frame without any issues, but this seems like a lot of code for a simple task. Surely there is a way to do this more code-efficiently, perhaps with plyr or reshape, or maybe I'm just looking for some code golf.

Thanks in advance.

share|improve this question
Why do you want to do this? –  blindJesse Oct 21 '12 at 23:06
add comment

2 Answers

up vote 3 down vote accepted

One does wonder why you need to do this, but regardless...

A base solution using rep

with(testFrame, data.frame(category = rep(category, opportunities), 
    indicator =  unlist(mapply(rep, times = c(successes,  opportunities-successes), 
      MoreArgs = list(x = c(0,1))))))

A data.table solution (coding elegance (perhaps a code golf competitor)

DT <- data.table(testFrame)
DT[,list(indicator = rep(c(0,1), c(successes,  opportunities-successes))), by = category]
share|improve this answer
This has sent me down the path to a wonderful world of data.table. Thanks so much. –  isDotR Oct 21 '12 at 23:48
That is good news indeed! –  mnel Oct 22 '12 at 0:04
add comment

and here is the plyr solution you were looking for:

ddply(testFrame, .(category), function(x) {
     data.frame(raw = c(rep(1,x$success), rep(0, x$opportunities - x$success)), 
        category = x$category)
share|improve this answer
Thanks for this; helps me better understand plyr. –  isDotR Oct 21 '12 at 23:47
add comment

Your Answer


