15
votes
$\begingroup$

I'm having following problem while doing some analysis with R.

I have a dataframe like this:

Name | Group | Count
Person 1 | A | 3
Person 2 | A | 1
Person 3 | A | 0
Person 1 | B | 5 
Person 2 | B | 0
Person 3 | B | 1
Person 1 | C | 1

and I'd need to "expand" it (not sure if the right term) to be like this:

Person 1 | A
Person 1 | A
Person 1 | A
Person 2 | A
Person 1 | B
Person 1 | B

etc.

So it takes value of pair Person 1 and A (in this example, 3) and makes three rows with Person 1 and A and does so for every Person - Group -combination. Can't figure out any good words for searching online.

$\endgroup$
4
  • $\begingroup$ Try the reshape() function $\endgroup$
    – guest
    Commented Mar 23, 2012 at 15:43
  • $\begingroup$ You should explore the reshape2 package in R. It might also help to dput 2 example dataframes: one with the input and one with the output. $\endgroup$
    – Zach
    Commented Mar 23, 2012 at 15:45
  • $\begingroup$ I provided an answer but I guess this more of an R programming question than a statistical question, so maybe it should be migrated somewhere else. $\endgroup$
    – Gala
    Commented Mar 23, 2012 at 16:11
  • $\begingroup$ Thanks Gaël for answer and helping with the formatting in my question. $\endgroup$ Commented Mar 23, 2012 at 16:46

3 Answers 3

10
votes
$\begingroup$

While it is a very useful package, I think reshape is overkill in this case, rep can do the job.

Here are some example data:

df <- data.frame(
     name=c("Person 1", "Person 2", "Person 3", "Person 1", "Person 2", "Person 3"),
     group=c("A", "A", "A", "B", "B", "B"),
     count=c(3,1,0,5,0,1))

Now, to “expand” it:

expanded <- data.frame(name = rep(df$name, df$count),
                       group = rep(df$group, df$count))

I could not find a way to work directly on the data frame off the top of my head so I am working on each variable separately and then reassembling them, which is a bit ugly but should be OK as long as you take care of always using the same variable for the counts.

$\endgroup$
2
  • 7
    $\begingroup$ How about this: df[rep(seq_len(nrow(df)), df$count), 1:2]? $\endgroup$
    – chl
    Commented Mar 23, 2012 at 17:19
  • $\begingroup$ @chl, you sir are brilliant! $\endgroup$
    – Chris
    Commented Oct 12, 2016 at 1:34
15
votes
$\begingroup$

You can use the untable function from the reshape package.

Given the above df (by @Gaël Laurans)

library(reshape)

expanded<-untable(df[,c(1,2)], num=df[,3])

name group
1   Person 1     A
1.1 Person 1     A
1.2 Person 1     A
2   Person 2     A
4   Person 1     B
4.1 Person 1     B
4.2 Person 1     B
4.3 Person 1     B
4.4 Person 1     B
6   Person 3     B
$\endgroup$
1
  • $\begingroup$ untable does exactly what I mentioned in my comment :-) Thanks for reminding me of that function! $\endgroup$
    – chl
    Commented Mar 24, 2012 at 20:32
1
vote
$\begingroup$

And uncount from tidyr now gives the same result as above.

library(tidyr)
df %>% uncount(Count)
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.