[R] apply with a division
Gavin Simpson
gavin.simpson at ucl.ac.uk
Fri Jul 4 09:43:04 CEST 2008
[Sorry, I seem to have misplaced the original posting, hence I'll reply
here as I haven't seen this solution mentioned yet]
See ?sweep - this is very general function for this sort of operation.
Note that mat is the OP's data as a matrix, not a data frame. This
doesn't work if mat is a data frame.
> mat
[,1] [,2] [,3]
[1,] 124 120 134
[2,] 165 163 174
[3,] 52 51 43
[4,] 179 171 166
[5,] 239 238 235
> sweep(mat, 2, mat[1,], "/")
[,1] [,2] [,3]
[1,] 1.0000000 1.000000 1.0000000
[2,] 1.3306452 1.358333 1.2985075
[3,] 0.4193548 0.425000 0.3208955
[4,] 1.4435484 1.425000 1.2388060
[5,] 1.9274194 1.983333 1.7537313
HTH
G
On Thu, 2008-07-03 at 20:39 -0500, Marc Schwartz wrote:
> on 07/03/2008 05:04 PM Greg Kettler wrote:
> > Hi,
> > I'd like to normalize a dataset by dividing each row by the first row.
> > Very simple, right?
> > I tried this:
> >
> >> expt.fluor
> > X1 X2 X3
> > 1 124 120 134
> > 2 165 163 174
> > 3 52 51 43
> > 4 179 171 166
> > 5 239 238 235
> >
> >> first.row <- expt.fluor[1,]
> >> normed <- apply(expt.fluor, 1, function(r) {r / first.row})
> >> normed
> > [[1]]
> > X1 X2 X3
> > 1 1 1 1
> >
> > [[2]]
> > X1 X2 X3
> > 1 1.330645 1.358333 1.298507
> >
> > [[3]]
> > X1 X2 X3
> > 1 0.4193548 0.425 0.3208955
> >
> > [[4]]
> > X1 X2 X3
> > 1 1.443548 1.425 1.238806
> >
> > [[5]]
> > X1 X2 X3
> > 1 1.927419 1.983333 1.753731
> >
> > Ugly! The values are right, but why didn't I get another 2D array
> > back? Shouldn't the division in my inline function return a vector?
> >
> > Thanks,
> > Greg
>
> More than likely, expt.fluor is a data frame and not a matrix. Since a
> data frame is a list based object, you get a list returned when dividing
> by the first row, which is a data frame (not a vector) by itself.
>
> You could do this, using unlist():
>
> > t(apply(expt.fluor, 1, function(x) x / unlist(expt.fluor[1, ])))
> X1 X2 X3
> 1 1.0000000 1.000000 1.0000000
> 2 1.3306452 1.358333 1.2985075
> 3 0.4193548 0.425000 0.3208955
> 4 1.4435484 1.425000 1.2388060
> 5 1.9274194 1.983333 1.7537313
>
>
> Alternatively, just coerce expt.fluor to a matrix first:
>
> expt.fluor <- as.matrix(expt.fluor)
>
> > t(apply(expt.fluor, 1, function(x) x / expt.fluor[1, ]))
> X1 X2 X3
> 1 1.0000000 1.000000 1.0000000
> 2 1.3306452 1.358333 1.2985075
> 3 0.4193548 0.425000 0.3208955
> 4 1.4435484 1.425000 1.2388060
> 5 1.9274194 1.983333 1.7537313
>
>
> Of course, you could also do this, leaving expt.fluor as a data frame:
>
> > do.call(rbind, apply(expt.fluor, 1, function(x) x / expt.fluor[1, ]))
> X1 X2 X3
> 1 1.0000000 1.000000 1.0000000
> 2 1.3306452 1.358333 1.2985075
> 3 0.4193548 0.425000 0.3208955
> 4 1.4435484 1.425000 1.2388060
> 5 1.9274194 1.983333 1.7537313
>
>
> You could also do the transpose first, which in effect does a coercion
> to a matrix:
>
> > apply(t(expt.fluor), 1, function(x) x / x[1])
> X1 X2 X3
> 1 1.0000000 1.000000 1.0000000
> 2 1.3306452 1.358333 1.2985075
> 3 0.4193548 0.425000 0.3208955
> 4 1.4435484 1.425000 1.2388060
> 5 1.9274194 1.983333 1.7537313
>
>
> Finally, use sapply() in a column-wise fashion:
>
> > sapply(expt.fluor, function(x) x / x[1])
> X1 X2 X3
> [1,] 1.0000000 1.000000 1.0000000
> [2,] 1.3306452 1.358333 1.2985075
> [3,] 0.4193548 0.425000 0.3208955
> [4,] 1.4435484 1.425000 1.2388060
> [5,] 1.9274194 1.983333 1.7537313
>
>
> Which approach you take is predicated on various factors, including
> personal style, readability and what you will ultimately do with the
> result. My preference would be to use sapply() as in the final example.
>
> HTH,
>
> Marc Schwartz
>
> ______________________________________________
> R-help at r-project.org 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