为什么 na.rm=TRUE 不适用于 R 中的加权 SD?
Why does na.rm=TRUE not work for weighted SD in R?
我有一个包含 10 列房价的数据框,在某些情况下,包括 NA。
我想创建一个 weighted sd
的新列,但是对于有几个 NA 的行,我得到以下错误:
Error in e2[[j]] : subscript out of bounds
我每行使用的内容(并且适用于没有 NA 的行):
weighted.sd(my.df[40,2:10], c(9,9,9,9,9,9,9,9,9), na.rm = TRUE)
例子
library(radiant.data)
data("mtcars")
mtcars[mtcars == 0] <- NA
weighted.sd(mtcars[18,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#works
weighted.sd(mtcars[5,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#issue here
这里有什么问题?如何创建一个新列,每行具有加权 SD?
问题似乎是 weighted.sd()
不会像您期望的那样跨数据框的行运行。
运行 weighted.sd
我们可以看到代码:
weighted.sd <- function (x, wt, na.rm = TRUE)
{
if (na.rm) {
x <- na.omit(x)
wt <- na.omit(wt)
}
wt <- wt/sum(wt)
wm <- weighted.mean(x, wt)
sqrt(sum(wt * (x - wm)^2))
}
在您的示例中,您输入的不是 x
的矢量,而是数据框的单行。由于 NA
值 - 而不是向量的元素,函数 na.omit(x)
将删除整行。
您可以尝试使用 as.numeric()
将行转换为向量,但是由于 wt
中删除了 NA
的方式,此函数也将失败。
看起来像这样的东西可能就是你想要的。当然,您必须小心输入 x
.
的有效列
weighted.sd2 <- function (x, wt, na.rm = TRUE) {
x <- as.numeric(x)
if (na.rm) {
is_na <- is.na(x)
x <- x[!is_na]
wt <- wt[!is_na]
}
wt <- wt/sum(wt)
wm <- weighted.mean(x, wt)
sqrt(sum(wt * (x - wm)^2))
}
weighted.sd2(mtcars[18,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#works
# [1] 26.76086
weighted.sd2(mtcars[5,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#issue here
# [1] 116.545
要将此应用于所有列,您可以使用 apply()
。
mtcars$weighted.sd <- apply(mtcars[,1:11], 1, weighted.sd2, wt = rep(11, 11))
mpg cyl disp hp drat wt qsec vs am gear carb weighted.sd
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 NA 1 4 4 52.61200
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 NA 1 4 4 52.58011
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 37.06108
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 NA 3 1 78.36300
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 NA NA 3 2 116.54503
...
如果你按住 CTRL 并点击 weigted.sd
函数你可以看到源代码:
function (x, wt, na.rm = TRUE)
{
if (na.rm) {
x <- na.omit(x)
wt <- na.omit(wt)
}
wt <- wt/sum(wt)
wm <- weighted.mean(x, wt)
sqrt(sum(wt * (x - wm)^2))
}
当你 运行 它时,值向量包含没有 NA 的值并且它被减少。但是weigth vector和之前一样长,导致报错
解决方案是:
weighted.sd(mtcars[5,!is.na(mtcars[5,1:11])],
c(11,11,11,11,11,11,11,11,11,11,11)[!is.na(mtcars[5,1:11])], na.rm = TRUE)
这不是很优雅...但它完成了工作!
我有一个包含 10 列房价的数据框,在某些情况下,包括 NA。
我想创建一个 weighted sd
的新列,但是对于有几个 NA 的行,我得到以下错误:
Error in e2[[j]] : subscript out of bounds
我每行使用的内容(并且适用于没有 NA 的行):
weighted.sd(my.df[40,2:10], c(9,9,9,9,9,9,9,9,9), na.rm = TRUE)
例子
library(radiant.data)
data("mtcars")
mtcars[mtcars == 0] <- NA
weighted.sd(mtcars[18,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#works
weighted.sd(mtcars[5,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#issue here
这里有什么问题?如何创建一个新列,每行具有加权 SD?
问题似乎是 weighted.sd()
不会像您期望的那样跨数据框的行运行。
运行 weighted.sd
我们可以看到代码:
weighted.sd <- function (x, wt, na.rm = TRUE)
{
if (na.rm) {
x <- na.omit(x)
wt <- na.omit(wt)
}
wt <- wt/sum(wt)
wm <- weighted.mean(x, wt)
sqrt(sum(wt * (x - wm)^2))
}
在您的示例中,您输入的不是 x
的矢量,而是数据框的单行。由于 NA
值 - 而不是向量的元素,函数 na.omit(x)
将删除整行。
您可以尝试使用 as.numeric()
将行转换为向量,但是由于 wt
中删除了 NA
的方式,此函数也将失败。
看起来像这样的东西可能就是你想要的。当然,您必须小心输入 x
.
weighted.sd2 <- function (x, wt, na.rm = TRUE) {
x <- as.numeric(x)
if (na.rm) {
is_na <- is.na(x)
x <- x[!is_na]
wt <- wt[!is_na]
}
wt <- wt/sum(wt)
wm <- weighted.mean(x, wt)
sqrt(sum(wt * (x - wm)^2))
}
weighted.sd2(mtcars[18,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#works
# [1] 26.76086
weighted.sd2(mtcars[5,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#issue here
# [1] 116.545
要将此应用于所有列,您可以使用 apply()
。
mtcars$weighted.sd <- apply(mtcars[,1:11], 1, weighted.sd2, wt = rep(11, 11))
mpg cyl disp hp drat wt qsec vs am gear carb weighted.sd
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 NA 1 4 4 52.61200
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 NA 1 4 4 52.58011
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 37.06108
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 NA 3 1 78.36300
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 NA NA 3 2 116.54503
...
如果你按住 CTRL 并点击 weigted.sd
函数你可以看到源代码:
function (x, wt, na.rm = TRUE)
{
if (na.rm) {
x <- na.omit(x)
wt <- na.omit(wt)
}
wt <- wt/sum(wt)
wm <- weighted.mean(x, wt)
sqrt(sum(wt * (x - wm)^2))
}
当你 运行 它时,值向量包含没有 NA 的值并且它被减少。但是weigth vector和之前一样长,导致报错
解决方案是:
weighted.sd(mtcars[5,!is.na(mtcars[5,1:11])],
c(11,11,11,11,11,11,11,11,11,11,11)[!is.na(mtcars[5,1:11])], na.rm = TRUE)
这不是很优雅...但它完成了工作!