[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