1

我有一个多层次的结构,我需要做的是为每个人标准化(这是更高级别的单位,每个单位都有几个单独的措施)。

考虑:

  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

我曾经apply(data, 2, scale)为每个人标准化(这也标准化了 ID 和度量,但没关系)。

但是,我如何确保分别对ID == 1,ID == 2和进行标准化ID == 3?--> 每个observation- mean of 3 scores,除以standard deviation for 3 scores)。

我正在考虑一个for循环,但问题是我想引导它(换句话说,为一个大数据集复制整个过程 1000 次,所以速度非常重要)。

额外信息:ID 可以有可变的测量值,所以并不是它们都有 3 个测量分数。

dput数据是:

structure(list(ID = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), measure = c(1L, 
2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), score = c(5L, 7L, 3L, 10L, 5L, 
3L, 4L, 1L, 1L)), .Names = c("ID", "measure", "score"), class = "data.frame", row.names = c(NA, 
-9L))
4

1 回答 1

3

这是一个lapply解决split方案并假设您的数据是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

产生相同结果的另一种方法是:

> simplify2array(lapply(split(DF[,-1], DF[,1]), scale))

此替代方案避免使用apply内部lapply调用。

这里split将数据划分为由定义的组ID并返回一个列表,因此您可以使用lapply循环遍历列表的每个元素应用scale

@Roland 建议使用ddplyfrom plyr :

> 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

导入您的数据(这是回答最后一条评论)

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)
于 2013-04-15T11:14:56.533 回答