2013-02-28 142 views
2

这似乎不应该太困难,但是我对此很难接受。比方说,比如我有以下数据帧:用R中的矢量划分数据帧或矩阵

set.seed(99) 
data <- data.frame(Names=rep(c('A','B'),5), 
        First = rnorm(10), 
        Second = rnorm(10), 
        Third = rnorm(10)) 

我要的是用平均A的这个我可以通过计算来划分整个数据帧:

a.mean < - sapply(数据[$名称==“A”,2:4],平均)

但是当我尝试通过矢量像这样把整个数据帧我没有得到正确的价值观:

normalized.data <- data[2:4]/a.mean 
normalized.data$Names <- data$Names 
sapply(data[normalized.data$Names == 'A', 2:4], mean) 

First  Second  Third 
0.2578018 -0.5864073 0.1156760 

Wheras我想要的是A的归一化平均数现在等于1.是否有这样做的方法?

+0

由于您从未使用过'B'数据,所以让我们摆脱它 – 2013-02-28 14:15:45

+0

请注意最后一行中的拼写错误。您正在计算原始数据的柱状图,而不是标准化数据。 – Roland 2013-02-28 14:21:25

回答

4
set.seed(99) 
data <- data.frame(Names=rep(c('A','B'),5), 
        First = rnorm(10), 
        Second = rnorm(10), 
        Third = rnorm(10)) 

a.mean <- sapply(data[data$Names == 'A', 2:4], mean) 
data[,2:4] <- sweep(data[,2:4],MARGIN=2,a.mean,"/") 

(norm.mean <- sapply(data[data$Names == 'A', 2:4], mean)) 
## First Second Third 
##  1  1  1 

根据您的应用程序,它可能更容易使Names列是该行的名称改为:

data <- data.frame(First = rnorm(10), 
        Second = rnorm(10), 
        Third = rnorm(10), 
        row.names=rep(c('A','B'),5)) 

我也喜欢subset(data,Names=='A')的可读性(虽然不建议用于编程:看https://github.com/hadley/devtools/wiki/Evaluation

+0

与双转置除法相比,使用sweep有优势吗? – Dave 2013-03-01 01:16:35

+0

我发现它更具可读性,它同样适用于行或列操作(通过使用'MARGIN = 1'和'MARGIN = 2',但我不认为性能差别很大(甚至可能会稍微慢一些)。 – 2013-03-01 02:53:55

2
set.seed(99) 
data <- data.frame(Names=rep(c('A','B'),5), 
        First = rnorm(10), 
        Second = rnorm(10), 
        Third = rnorm(10)) 

a.mean <- colMeans(data[data$Names == 'A', 2:4]) 


normalized.data <- as.data.frame(t(t(data[,2:4])/a.mean)) 


normalized.data$Names <- data$Names 
colMeans(normalized.data[normalized.data$Names == 'A', 1:3]) 

#First Second Third 
#1  1  1 
2

哦,别介意:你没有按照自己认为的方式划分。将矩阵除以值的向量不会将每列除以给定的值。

Rgames> foo 
    [,1] [,2] [,3] 
[1,] 5 3 7 
[2,] 5 3 7 
[3,] 5 3 7 
[4,] 5 3 7 
[5,] 5 3 7 
Rgames> foo/c(1,2,3) 
     [,1] [,2]  [,3] 
[1,] 5.000000 1.0 3.500000 
[2,] 2.500000 3.0 2.333333 
[3,] 1.666667 1.5 7.000000 
[4,] 5.000000 1.0 3.500000 
[5,] 2.500000 3.0 2.333333 
+2

准确地说,除数被回收。这就是为什么你可以简单地转置foo来获得想要的结果。 – Roland 2013-02-28 14:30:08