R Dplyr mutate,计算每行标准差

8

我将尝试从数据框的特定列计算平均值和标准差,并将这些值返回到数据框中的新列。对于平均值,我可以让它正常工作:

library(dplyr)
mtcars = mutate(mtcars, mean=(hp+drat+wt)/3)

然而,当我尝试计算标准差时,会出现问题,因为我不能像计算平均值那样轻松地硬编码方程。所以,我尝试使用以下函数:

mtcars = mutate(mtcars, mean=(hp+drat+wt)/3, stdev = sd(hp,drat,wt))

导致错误 "Error in sd(hp, drat, wt) : unused argument (wt)"。我该如何更正语法?谢谢。

4
为了计算均值,你实际上写出了公式,但是为了计算标准偏差,你以一种奇怪的方式使用了内置的sd函数。你觉得这看起来不一致吗? - David Arenburg
是的,这就是为什么我说“当我尝试对标准差执行相同操作时,会遇到问题,因为我不能像对均值那样轻松地硬编码方程。所以,我尝试使用一个函数。”我不确定你为什么认为我以某种奇怪的方式使用了sd函数,尽管我确信这是正确的。sd函数似乎接受一个数字向量,例如sd(c(3,5,6))。虽然我确信这对你来说很明显,但我做的事情为什么不正确?谢谢。 - user2808302
也许@DavidArenburg所建议的是您对sd的调用是不正确的,这是一个常见的错误方式。例如,尝试使用sd(1,2,3),然后阅读?sd并查看(1)它将第一个参数描述为“x:数字向量”,以及(2)它明确不包括“…”(省略号,允许提供任意数量的参数,就像您正在提供的那样)。 - r2evans
@user2808302 如果存在NA,则使用+获取平均值可能无法按预期工作。在meanrowMeans中,有删除NA的选项,即na.rm=TRUE - akrun
3个回答

10
您可以尝试:
library(dplyr)
library(matrixStats)
nm1 <- c('hp', 'drat', 'wt')
res1 <- mtcars %>% 
           mutate(Mean= rowMeans(.[nm1]), stdev=rowSds(as.matrix(.[nm1])))

head(res1,3)
#   mpg cyl disp  hp drat    wt  qsec vs am gear carb     Mean    stdev
#1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 38.84000 61.62969
#2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 38.92500 61.55489
#3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 33.05667 51.91809

或者使用do
res2 <- mtcars %>% 
             rowwise() %>%
             do(data.frame(., Mean=mean(unlist(.[nm1])),
                         stdev=sd(unlist(.[nm1]))))

head(res2,3)
#   mpg cyl disp  hp drat    wt  qsec vs am gear carb     Mean    stdev
#1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 38.84000 61.62969
#2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 38.92500 61.55489
#3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 33.05667 51.91809

@arkrun。谢谢,但是当我运行你的第一段代码时,出现了一个错误:“Error in .[nm1] : object of type 'closure' is not subsettable”。 - user2808302
@user2808302 我不确定问题出在哪里。你是否使用最新版本的 dplyr?我使用的是 dplyr_0.4.1.9000 - akrun
谢谢@akrun。我刚刚执行了install.packages("dplyr"),然后sessionInfo()显示它是版本dplyr_0.4.1。我重新运行代码,但仍然出现相同的错误! - user2808302
你正在选择列,所以你应该将 as.matrix(.[nm1]) 编辑为 as.matrix(.[ ,nm1]) - Ehsan M. Kermani
我们从一个数据框中选择列,其中 .[nm1] 默认获取列,然后只转换为 matrix。如果它已经是矩阵,则 .[, nm1] 就是正确的方式。因此,在这种情况下,两种方法都可以使用。如果您有疑问,请检查两种情况的结果是否相同。 - akrun
显示剩余5条评论

5

你也可以编写自己的向量化RowSD函数,如下所示

RowSD <- function(x) {
  sqrt(rowSums((x - rowMeans(x))^2)/(dim(x)[2] - 1))
}

然后

mtcars %>% 
  mutate(mean = (hp + drat + wt)/3, stdev = RowSD(cbind(hp, drat, wt)))
##     mpg cyl  disp  hp drat    wt  qsec vs am gear carb      mean     stdev
## 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4  38.84000  61.62969
## 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4  38.92500  61.55489
## 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1  33.05667  51.91809
## 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1  38.76500  61.69136
## 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2  60.53000  99.13403
## 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1  37.07333  58.82726
## ...

工作得非常好。 - Vass

4

无需进行太多更改,只需添加rowwise()(感谢@akrun的评论),并在列名上加上c(...)(以解决错误):

library(dplyr)
mtcars %>%
    rowwise() %>%
    mutate(mean=(hp+drat+wt)/3, stdev = sd(c(hp,drat,wt)))
## Source: local data frame [32 x 13]
## Groups: <by row>
##     mpg cyl  disp  hp drat    wt  qsec vs am gear carb     mean     stdev
## 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 38.84000  61.62969
## 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 38.92500  61.55489
## 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 33.05667  51.91809
## 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 38.76500  61.69136
## 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 60.53000  99.13403
## 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 37.07333  58.82726
## 7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 83.92667 139.49371
## 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 22.96000  33.81056
## 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 34.02333  52.80875
## 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4 43.45333  68.88985
## ..  ... ...   ... ...  ...   ...   ... .. ..  ...  ...      ...       ...

1
嗨,使用相同的命令会给我相同的 sd 值。平均值工作正常。请查看下面的输出。 - Chirag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接