【问题标题】:Dividing a Data Frame or Matrix by a Vector in R在R中将数据框或矩阵除以向量
【发布时间】:2013-02-14 18:00:11
【问题描述】:

这似乎不应该太难,但我很难做到这一点。例如,我有以下数据框:

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

我想要的是将整个数据框除以 A 的平均值。我可以通过以下方式计算:

a.mean

但是当我尝试像这样将整个数据框除以该向量时,我没有得到正确的值:

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

我想要的是 A 的标准化平均值现在等于 1。有没有办法做到这一点?

【问题讨论】:

  • 既然你从来没有使用过B 数据,那么让我们摆脱它
  • 注意最后一行的错字。您正在计算原始数据的 colmeans,而不是标准化数据。

标签: r scale normalization division


【解决方案1】:
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

【讨论】:

  • 与双转置除法相比,使用扫描有优势吗?
  • 我发现它更具可读性,并且它同样适用于行或列操作(通过使用 MARGIN=1MARGIN=2,但我认为性能差异并不大(它甚至可能是微不足道的)慢)。
【解决方案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 

【讨论】:

    【解决方案3】:

    哦,没关系:您并没有按照您认为的方式进行划分。将矩阵除以值向量不会将每一列除以给定值。

    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
    

    【讨论】:

    • 没错,除数被回收了。这就是为什么您可以简单地转置 foo 以获得所需的结果。
    猜你喜欢
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    • 2019-12-15
    • 2018-06-13
    • 2015-04-23
    相关资源
    最近更新 更多