Сводка
Оказывается, разница в том, как вычисляются отклонения. Если у нас есть только переменные x
и y
, где x
имеет несколько NA, то функция cov
будет вычислять y_mean
и var_y
, используя все наблюдения в y
. Функция cor
, с другой стороны, будет вычислять y_mean
и var_y
, используя только значения в y
, которые соответствуют не пропущенным значениям в x
.
Для меня "pairwise.complete.obs" должен означать, что должна быть вся статистика, которая может быть вычислена с учетом всех наблюдений, и, таким образом, функция cor
некорректна для парных удалений. Возможно, вопрос мнения, и, возможно, не имеет большого значения при большем количестве наблюдений, но явно нежелательно, чтобы эти две функции молча давали разные результаты.
Мотивация
Следующий вопрос StackoverFlow объясняет, как смотреть на код C ++: Как просмотреть исходный код функции? и вот ссылка на коддля функции C_cov
: https://svn.r -project.org / R / trunk / src / library / stats / src / cov.c
Ниже приведен R-код, демонстрирующийразличия в вычислениях. Сначала автоматический расчет:
dat <- data.frame(x = rnorm(10), y = rnorm(10))
dat$x[c(1,3)] <- NA
d <- cov(dat, use = "pairwise.complete.obs")
cov_version <- cov2cor(d)
cor_version <- cor(dat, use = "pairwise.complete.obs")
Вычислить вручную
#Computing the covariance is the same for both cor and cov functions
n <- length(dat$x[!is.na(dat$x)]) #n of non-missing values
x_bar <- mean(dat$x, na.rm = TRUE)
y_bar <- mean(dat$y[!is.na(dat$x)]) #mean of y values where x is not NA
n1 <- n -1
s_x <- dat$x[!is.na(dat$x)] - x_bar
s_y <- dat$y[!is.na(dat$x)] - y_bar
ss_xy <- sum(s_x*s_y) #sums of squares (x, y)
cov_xy <- ss_xy / n1 #same results as cov(dat, use = "pairwise.complete.obs")
all.equal(cov_xy, d[1,2])
[1] TRUE
#The cor approach to computing variances
ss_x <- sum(s_x*s_x)
ss_y <- sum(s_y*s_y)
var_x <- ss_x / n1
var_y <- ss_y / n1
cor_xy <- cov_xy / (sqrt(var_x) *sqrt(var_y)) #same as cor(dat, use = "pairwise.complete.obs")
all.equal(cor_xy, cor_version[1,2])
[1] TRUE
#The cov approach to computing variances, different for the variable without missing values
y_bar2 <- mean(dat$y) #all values of y
s_y2 <- dat$y - y_bar2
ss_y2 <- sum(s_y2*s_y2)
var_y2 <- ss_y2 / (length(dat$y) - 1) #n comes from all values of y
cov_cor <- cov_xy / (sqrt(var_x) * sqrt(var_y2))
all.equal(cov_cor, cov_version[1,2])
[1] TRUE