Oliver
Oliver

Reputation: 3682

aggregate and transform a dataset

I have a sample dataset like the following:

df=data.frame(iter=c(1, 1, 2, 2), exp=c("A", "B", "A", "B"), 
      val=c(2.3, 3.6, 4.0, 5.0))

The tabular form will be:

  iter exp val
    1   A  2.3
    1   B  3.6
    2   A  4.0
    2   B  5.0

I am trying to transform it in a way to group A and B, add a ratio column with value such as df$val[1]/df$val[2], df$val[3]/df$val[4], so the end result looks like:

   iter ratio
   1    2.3/3.6
   2    4.0/5.0

I feel this should be a job of ddply, but I couldn't see a path to get it done. Any help is appreciated.

Upvotes: 0

Views: 141

Answers (3)

Matthew Lundberg
Matthew Lundberg

Reputation: 42679

Here's a solution in base. It's somewhat more complex than the plyr solution, but perhaps it is instructive.

do.call(rbind,
   by(df,
      df$iter,
      function(x) {
         with(x, 
            data.frame(
               iter=iter[1],
               ratio=val[which(exp=='A')]/val[which(exp=='B')] ## Or use paste to get a text representation of the ratio
            )
         )
      }
   )
)
## i iter    ratio
## 1    1 0.638889
## 2    2 0.800000

It splits the data frame by the iter column, then takes the ratio of the A val element over the B element. It assumes that there is only one such value per level.

Upvotes: 0

Ricardo Saporta
Ricardo Saporta

Reputation: 55420

library(data.table)
DT <- as.data.table(df)
DT[, list(ratio= val[exp=="A"] / val[exp=="B"]), by=iter]

   iter    ratio
1:    1 0.638889
2:    2 0.800000

Upvotes: 0

dotcomken
dotcomken

Reputation: 245

Try this:

library(plyr)
df2 <- ddply(df, .(iter), summarise, ratio=paste(val[which(exp=="A")],"/",val[which(exp=="B")],sep=""))

Which gave me:

  iter   ratio
     1 2.3/3.6
     2     4/5

Upvotes: 2

Related Questions