Проблема с подсчетом нулевых значений в операторе if в R - PullRequest
0 голосов
/ 10 марта 2020

Я передаю некоторые данные в простой кодовый блок в R, который считает нулевые значения, а затем выполняет вычисление временных рядов ARIMA. Я написал очень простое выражение «если», которое считает нулевые значения во временном ряду, и если они меньше определенного значения, игнорирует этот столбец и переходит к следующему (так как вменение ARIMA требует определенного количества ненулевые данные для работы, в противном случае он возвращает ошибку). Подсчет нулей, кажется, работает нормально, но оператор if ведет себя очень странно и не работает. Я включил оператор print для подсчета нулей внутри и вне оператора if, но оператор if передает код в l oop, когда оператор 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 работает неправильно, так как передает данные в условное выражение arima внутри оператора if, даже если число нулей равно на длину временного ряда. Вот результат:

[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, и это приведет к сбою аримы - следовательно, оператор if должен пропустить эту строку. Но это не делает этого.

Где я иду не так, пожалуйста? Это должно быть очень просто, но это не имеет никакого смысла! Я не пишу много кода R, обычно Python. Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 10 марта 2020
sum(is.na(ts) != length(ts))

, вероятно, должно быть

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

Пояснение, что пошло не так: В R любое число, кроме 0, оценивается как ИСТИНА. Например:

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 (и других арифметических c функций) и обрабатывает их в этих случаях как 1 (TRUE) и 0 (FALSE) .

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

Оценивает некоторый вектор значений ИСТИНА и ЛОЖЬ

и

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

счастливо суммирует их;)

Вот почему ваш код не вызывало никаких ошибок, потому что вроде работало, просто не делало того, что намеревалось сделать ... это мои самые страшные ошибки;)

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