[R] apply with a division

Marc Schwartz marc_schwartz at comcast.net
Fri Jul 4 03:39:48 CEST 2008


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



More information about the R-help mailing list