[R] group bunch of lines in a data.frame, an additional requirement

Gabor Grothendieck ggrothendieck at gmail.com
Fri Sep 15 02:55:29 CEST 2006


Here are three different ways to do it:

# base R
fb <- function(x)
   c(V1 = x$V1[1], V4 = x$V4[1], V2.mean = mean(x$V2),
     V3.mean = mean(x$V3), n = length(x$V1))
do.call(rbind, by(DF, DF[c(1,4)], fb))

# package doBy
library(doBy)
summaryBy(V2 + V3 ~ V1 + V4, DF, FUN = c(mean, length))[,-5]

# package reshape
library(reshape)
f <- function(x) c(mean = mean(x), n = length(x))
cast(melt(DF, id = c(1,4)), V1 + V4 ~ variable, fun.aggregate = f)[,-6]

----

> # base R
> fb <- function(x)
+    c(V1 = x$V1[1], V4 = x$V4[1], V2.mean = mean(x$V2),
+      V3.mean = mean(x$V3), n = length(x$V1))
> do.call(rbind, by(DF, DF[c(1,4)], fb))
     V1 V4 V2.mean V3.mean n
[1,]  1  1     2.0     400 3
[2,]  3  1     5.0      70 1
[3,]  2  2     0.7      35 2
>
> # package doBy
> library(doBy)
> summaryBy(V2 + V3 ~ V1 + V4, DF, FUN = c(mean, length))[,-5]
  V1  V4 mean.V2 mean.V3 length.V3
1  A ID1     2.0     400         3
2  C ID1     5.0      70         1
3  B ID2     0.7      35         2
>
> # package reshape
> library(reshape)
> f <- function(x) c(mean = mean(x), n = length(x))
> cast(melt(DF, id = c(1,4)), V1 + V4 ~ variable, fun.aggregate = f)[,-6]
  V1  V4 V2_mean V2_n V3_mean
1  A ID1     2.0    3     400
2  B ID2     0.7    2      35
3  C ID1     5.0    1      70






---

> library(doBy)
> summaryBy(V2 + V3 ~ V1 + V4, DF, FUN = c(mean, length))[,-5]
  V1  V4 mean.V2 mean.V3 length.V3
1  A ID1     2.0     400         3
2  C ID1     5.0      70         1
3  B ID2     0.7      35         2
>
> library(reshape)
> f <- function(x) c(mean = mean(x), n = length(x))
> cast(melt(DF, id = c(1,4)), V1 + V4 ~ variable, fun.aggregate = f)[,-6]
  V1  V4 V2_mean V2_n V3_mean
1  A ID1     2.0    3     400
2  B ID2     0.7    2      35
3  C ID1     5.0    1      70



On 9/14/06, Emmanuel Levy <emmanuel.levy at gmail.com> wrote:
> Thanks Gabor, that is much faster than using a loop!
>
> I've got a last question:
>
> Can you think of a fast way of keeping track of the number of
> observations collapsed for each entry?
>
> i.e. I'd like to end up with:
>
> A 2.0 400 ID1 3 (3obs in the first matrix)
> B 0.7 35 ID2 2 (2obs in the first matrix)
> C 5.0 70 ID1 1 (1obs in the first matrix)
>
> Or is it required to use an temporary matrix that is merged later? (As
> examplified by Mark in a previous email?)
>
> Thanks a lot for your help,
>
>  Emmanuel
>
> On 9/13/06, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
> > See below.
> >
> > On 9/13/06, Emmanuel Levy <emmanuel.levy at gmail.com> wrote:
> > > Thanks for pointing me out "aggregate", that works fine!
> > >
> > > There is one complication though: I have mixed types (numerical and character),
> > >
> > > So the matrix is of the form:
> > >
> > > A 1.0 200 ID1
> > > A 3.0 800 ID1
> > > A 2.0 200 ID1
> > > B 0.5 20   ID2
> > > B 0.9 50   ID2
> > > C 5.0 70   ID1
> > >
> > > One letter always has the same ID but one ID can be shared by many
> > > letters (like ID1)
> > >
> > > I just want to keep track of the ID, and get a matrix like:
> > >
> > > A 2.0 400 ID1
> > > B 0.7 35 ID2
> > > C 5.0 70 ID1
> > >
> > > Any idea on how to do that without a loop?
> >
> > If V4 is a function of V1 then you can aggregate by it too and it will
> > appear but have no effect on the classification:
> >
> > > aggregate(DF[2:3], DF[c(1,4)], mean)
> >   V1  V4  V2  V3
> > 1  A ID1 2.0 400
> > 2  C ID1 5.0  70
> > 3  B ID2 0.7  35
> >
> >
> > >
> > >  Many thanks,
> > >
> > >     Emmanuel
> > >
> > > On 9/12/06, Emmanuel Levy <emmanuel.levy at gmail.com> wrote:
> > > > Hello,
> > > >
> > > > I'd like to group the lines of a matrix so that:
> > > > A 1.0 200
> > > > A 3.0 800
> > > > A 2.0 200
> > > > B 0.5 20
> > > > B 0.9 50
> > > > C 5.0 70
> > > >
> > > > Would give:
> > > > A 2.0 400
> > > > B 0.7 35
> > > > C 5.0 70
> > > >
> > > > So all lines corresponding to a letter (level), become a single line
> > > > where all the values of each column are averaged.
> > > >
> > > > I've done that with a loop but it doesn't sound right (it is very
> > > > slow). I imagine there is a
> > > > sort of "apply" shortcut but I can't figure it out.
> > > >
> > > > Please note that it is not exactly a matrix I'm using, the function
> > > > "typeof" tells me it's a list, however I access to it like it was a
> > > > matrix.
> > > >
> > > > Could someone help me with the right function to use, a help topic or
> > > > a piece of code?
> > > >
> > > > Thanks,
> > > >
> > > >   Emmanuel
> > > >
> > >
> > > ______________________________________________
> > > R-help at stat.math.ethz.ch mailing list
> > > https://stat.ethz.ch/mailman/listinfo/r-help
> > > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> > > and provide commented, minimal, self-contained, reproducible code.
> > >
> >
>



More information about the R-help mailing list