Re: [R] apply with a division

From: Marc Schwartz <marc_schwartz_at_comcast.net>
Date: Thu, 03 Jul 2008 20:39:48 -0500

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. Received on Fri 04 Jul 2008 - 01:42:18 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Fri 04 Jul 2008 - 08:31:18 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-help. Please read the posting guide before posting to the list.

list of date sections of archive