Рассчитать дисперсию вручную в R - PullRequest
0 голосов
/ 10 апреля 2020

Мне нужна ваша помощь здесь. Мне нужно вычислить дисперсию вручную в R. Я добился этого с помощью этих кодов, это недостаточно надежно для пропущенных значений и нечисловых c типов данных.

a= c(1,2,3,4,5)
k=mean(a,na.rm = T)
storage=a
for(i in 1:length(a)) {
  storage[i]= ((i-k)^2)
}
storage =sum((storage)/(length(a)-1))
storage

У меня возникают проблемы, когда У меня есть = c (1,2,3,4,5, c, NA). Пожалуйста, как мне отредактировать код?

Ответы [ 3 ]

2 голосов
/ 10 апреля 2020

Сначала несколько замечаний:

  1. В R вы можете выполнить операцию над целым вектором. Например, (c(1, 2, 3))^2 дает 1 4 9. Нет необходимости использовать for l oop.
  2. mean - не единственная функция, для которой требуется na.rm = TRUE; sum делает то же самое.
  3. В R векторы Atomi c (которые являются почти всеми векторами, не являющимися списком) могут иметь элементы только одного типа данных. Существует четыре основных типа: логический, целочисленный, двойной и символьный. Если в векторе имеется более одного типа, все элементы принудительно будут одинаковыми в следующем порядке: символ → двойной → целое → логический. Например, c(1, 'c') вернет символьный вектор "1", "c". Вот почему у вас были проблемы. (Примечание: если в векторе есть NA, его тип будет того же типа, что и вектор.)

К сожалению, для этого указанного c вектора, c(1,2,3,4,5,c,NA), я не Я думаю, что есть простой способ привести его к целому числу. Это потому, что в списке есть функция как элемент: функция c().

Однако эта функция работает всякий раз, когда x является атомом c вектором:

variance <- function(x){
  x = as.numeric(x)
  x = na.omit(x)
  m = mean(x)
  return(
    sum((x-m)^2, na.rm = TRUE)/(length(x) - 1)
  )
}

Сначала мы приведем вектор к цифре c, чтобы мы могли иметь дело с вектором как c(1, 2, 'a'). Затем мы удаляем NA, поэтому нам не нужно писать na.rm = TRUE в mean и sum. Затем мы просто записываем формулу.

Небольшое неудобство заключается в том, что при преобразовании вектора символов в число c мы получаем предупреждение о том, что сгенерировано NA s. Это можно решить, если вместо этого написать x = suppressWarnings(as.numeric(x)).

Если вы хотите, чтобы ваша функция могла обрабатывать списки с функциями, дайте мне знать.

0 голосов
/ 10 апреля 2020

Вы используете для l oop, но это действительно не нужно, вы можете сделать функцию для ее векторизации, которая удаляет NA из данных в качестве первого шага, путем преобразования в символ, а затем в число c векторных типов ( потому что c является функцией) ...

# Create data
set.seed(1)
x1 <- sample(1:10, 5)
x2 <- c(x1, c, NA)

# Make the function
varFunc <- function(x){
 # Convert to character then numeric (non numeric become NA) then remove NAs
  x <- as.numeric(as.character(x))[!is.na(as.numeric(as.character(x)))]
  # Return Variance 
  sum((x-mean(x))^2) / (length(x)-1)
}

# Use the function 
varFunc(x1)
varFunc(x2)

# Sanity check
var(x1)
var(x2, na.rm = TRUE)
0 голосов
/ 10 апреля 2020

Один из возможных подходов: сначала очистить a. Если вы начнете с чего-то вроде a = c(1, 2, 3, 4, 5, "c", NA), то a не будет храниться как переменная цифра c (из-за записи не цифра c). Сначала вы можете привести его к числовому c вектору, что даст дополнительную NA запись:

a = c(1, 2, 3, 4, 5, "c", NA)
a <- as.numeric(a)

a

## 1  2  3  4  5 NA NA

Затем вы можете установить исходный вектор, сохранив только записи из этого являются цифрами c (с помощью !):

a <- a[!is.na(as.numeric(a))]

a

## 1  2  3  4  5

Вы можете сделать это сразу после первоначального объявления, например, a. Грегор Томас также предложил na.omit(), который мог бы работать, если бы он правильно сочетался с as.numeric().

. Я заметил, что вы вычислили среднее значение, используя встроенную функцию mean() и na.rm = T ... если вы можете использовать тот же подход здесь, обратите внимание, что var() также имеет необязательный параметр na.rm = T. Я подозреваю, что вам не разрешено использовать его, поскольку вам было поручено вычислить дисперсию вручную, но, возможно, вы могли бы использовать это для проверки ваших ответов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...