【问题标题】:Calculate Variance Manually in R在 R 中手动计算方差
【发布时间】:2020-04-10 11:45:23
【问题描述】:

我需要你的帮助。我需要在 R 中手动计算方差。我已经用这个代码实现了它,它对于缺失值和非数字数据类型不够健壮。

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

当我有 a= c(1,2,3,4,5,c,NA) 时我遇到了麻烦 请问如何修改代码?

【问题讨论】:

  • 函数第一行:a = na.omit(a)

标签: r statistics


【解决方案1】:

首先,有几点观察:

  1. 在 R 中,您可以对整个向量进行操作。例如。 (c(1, 2, 3))^2 产生 1 4 9。无需使用for 循环。
  2. mean 不是唯一需要 na.rm = TRUE 的函数; sum 也是。
  3. 在 R 中,原子向量(几乎是所有不是列表的向量)只能包含一种数据类型的元素。有四种主要类型:逻辑、整数、双精度和字符。如果向量中有多个类型,则所有元素都强制相同,顺序如下:字符 → 双精度 → 整数 → 逻辑。例如,c(1, 'c') 将返回 字符向量 "1", "c"。这就是你遇到麻烦的原因。 (注意:如果向量中有NA,则其类型将与向量的类型相同。)

不幸的是,对于那个特定的向量c(1,2,3,4,5,c,NA),我认为没有一种简单的方法可以将其强制转换为整数。那是因为它是一个将函数作为元素的列表:函数c()。

但是,只要x 是原子向量,此函数就会起作用:

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(1, 2, 'a') 这样的向量。然后我们删除NA,所以我们不必在mean 和sum 中写na.rm = TRUE。然后我们就写下公式。

一个小的不便之处在于,在将字符向量转换为数字时,我们会收到一条警告,指出生成了 NAs。如果我们改写x = suppressWarnings(as.numeric(x)),就可以解决这个问题。

如果您希望您的函数能够处理带有函数的列表,请告诉我。

【讨论】:

    【解决方案2】:

    您正在使用 for 循环,但这实际上是不必要的,您可以创建一个函数来对其进行矢量化,作为第一步,通过转换为字符然后数字向量类型从数据中删除 NA(因为 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)
    

    【讨论】:

      【解决方案3】:

      一种可能的方法:首先,清理a。如果您以a = c(1, 2, 3, 4, 5, "c", NA) 之类的开头,则a 将不会存储为数字变量(因为非数字条目)。您可能首先将其强制转换为数字向量,这将提供一个额外的 NA 条目:

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

      然后,您可以通过仅保留其中是数字的条目(使用!)来子集原始向量:

      a <- a[!is.na(as.numeric(a))]
      
      a
      
      ## 1  2  3  4  5
      

      例如,您可以在初始声明 a 之后立即执行这些操作。 Gregor Thomas 还建议使用na.omit(),如果与as.numeric() 正确结合,它可以工作。

      我注意到您使用内置 mean() 函数和 na.rm = T... 计算平均值...如果您能够在此处使用相同的方法,请注意 var() 也有一个可选的 @ 987654334@ 参数。我怀疑你不允许使用它,因为你被指示手动计算方差,但也许你可以用它来检查你的答案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-04
        • 1970-01-01
        • 1970-01-01
        • 2018-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多