首页 > 解决方案 > 在 R 中的“if 语句”中计算空值的问题

问题描述

我将一些数据传递给 R 中的一个简单代码块,该代码块计算空值,然后执行 ARIMA 时间序列插补。我写了一个非常简单的“if”语句,它计算时间序列中的空值,如果它们小于一定数量,则忽略该列并转到下一个(因为 ARIMA 插补需要一定数量的非空数据才能工作,否则返回错误)。计算空值似乎可以正常工作,但是 if 语句的行为非常奇怪并且不起作用。我包含了一个打印语句来计算 if 语句内部和外部的空值,但是当 if 语句未执行时,if 语句将代码传递给循环。这是代码和输出:

stations <- c('BX1', 'BX2', 'BG3') # each station has a different data file
pollutants <- c('nox','no2','pm10','pm25') # each station contains data on a number of pollutants
for (s in stations) {
  print(paste('starting imputation for station ', s, sep=" "))
  s_result <- read.csv(paste("/path/to/file", s, "_rescaled.csv", sep=""))
  for (p in pollutants) {
    ts = c()
    pcol = paste0(p,"_iqr",sep="") # find the right column
    ts = s_result[[pcol]]  # get the time series from the column
    print(pcol) # check which pollutant we're working on
    print(length(ts)) # test the length of the time series
    print(sum(is.na(ts))) # test the number of nulls in the time series
    if (sum(is.na(ts) != length(ts))) {       # if the time series is not completely null
      print(sum(is.na(ts)))            # check the length of the time series again for testing
      usermodel <- arima(ts, order = c(10, 1, 0))$model      # calculate the arima
      p_result <- na_kalman(ts, model = usermodel, maxgap = 24)    # calculate the arima
      s_result <- cbind(s_result,p_result) # add the computed column to the dataframe
      names(s_result)[names(s_result) == "p_result"] <- paste0(p,"_imputed",sep ="")
    } else { # otherwise add a null column
      p_result <- c(NA, length=length(ts))
      s_result <- cbind(s_result,p_result) # enter a null column
      names(s_result)[names(s_result) == "p_result"] <- paste0(p,"_imputed",sep ="")
    }
  }
  filename = paste0("/path/to/file", s, "_imputed_test.csv", sep="")
  write.csv(s_result, filename, row.names = TRUE) 
  print(paste('completed imputation for station ', s, sep=" "))
}

问题是,这个 if 语句无法正常工作,因为它正在将数据传递给 if 语句中的 arima 插补,即使空值的数量等于时间序列的长度也是如此。这是输出:

[1] "starting imputation for station  BG1"
[1] "nox_iqr"
[1] 17520
[1] 4660
[1] 4660
[1] "no2_iqr"
[1] 17520
[1] 4664
[1] 4664
[1] "pm10_iqr"
[1] 17520
[1] 17520
[1] 17520
Error in arima(ts, order = c(10, 1, 0)) : 'x' must be numeric

显然有问题,对于 pm10 污染物,有 17520 个空值,与时间序列的长度相同。因此,if 语句不应在 'if' 语句中再次运行计算空值数量的行,因为应该绕过这行代码。IE。对于与列 pm10_iqr 相关的时间序列,空值数为 17520,时间序列的长度为 17520,这将导致 arima 失败 - 因此 if 语句应跳过此行。但它不这样做。

请问我哪里错了?这应该很简单,但没有任何意义!我不写很多 R 代码,通常是 Python。谢谢你的帮助!

标签: rif-statementnullarima

解决方案


sum(is.na(ts) != length(ts))

应该是

sum(is.na(ts)) != length(ts))

解释出了什么问题:在 R 中,除 0 以外的任何数字都计算为 TRUE。例如:

if (0) {print("evaluated to TRUE")} else {print("evaluated to FALSE")} and 

回报:

 [1] "evaluated to FALSE"

和:

if (5) {print("evaluated to TRUE")} else {print("evaluated to FALSE")}

回报:

[1] "evaluated to TRUE"

此外,R 接受布尔值 ( TRUE, FALSE) 作为sum(和其他算术函数)的参数,并在这些情况下将它们视为 1 ( TRUE) 和 0 ( FALSE)。

is.na(ts) != length(ts)

评估某个 TRUE 和 FALSE 向量

sum(is.na(ts) != length(ts))

愉快地总结它们;)

这就是为什么您的代码没有引发任何错误的原因,因为它可以正常工作,只是没有按照我们的意思行事……这些是我最担心的错误;)


推荐阅读