Here's an lapply
with split
solution and assuming your data is DF
> lapply(split(DF[,-1], DF[,1]), function(x) apply(x, 2, scale))
$`1`
measure score
[1,] -1 0
[2,] 0 1
[3,] 1 -1
$`2`
measure score
[1,] -1 1.1094004
[2,] 0 -0.2773501
[3,] 1 -0.8320503
$`3`
measure score
[1,] -1 1.1547005
[2,] 0 -0.5773503
[3,] 1 -0.5773503
An alternative which produces the same result is:
> simplify2array(lapply(split(DF[,-1], DF[,1]), scale))
This alternative avoids using apply
inside lapply
call.
Here's split
divides the data into groups defined by ID
and it returns a list, so you can use lapply
to loop over each element of the list applying scale
.
Using ddply
from plyr as @Roland suggests:
> library(plyr)
> ddply(DF, .(ID), numcolwise(scale))
ID measure score
1 1 -1 0.0000000
2 1 0 1.0000000
3 1 1 -1.0000000
4 2 -1 1.1094004
5 2 0 -0.2773501
6 2 1 -0.8320503
7 3 -1 1.1547005
8 3 0 -0.5773503
9 3 1 -0.5773503
Importing your data (this is to answer the last comment)
DF <- read.table(text=" ID measure score
1 1 1 5
2 1 2 7
3 1 3 3
4 2 1 10
5 2 2 5
6 2 3 3
7 3 1 4
8 3 2 1
9 3 3 1", header=TRUE)