Интерполировать значения NA в кадре данных с помощью na.approx

Я пытаюсь удалить NA из моего фрейма данных путем интерполяции с помощью na.approx(), но не может удалить все NA s.

Мой кадр данных - это 4096x4096 с отметкой 270.15 как флаг для недействительного значения. Мне нужно, чтобы данные были постоянными во всех точках, чтобы накормить метеорологическую модель. Вчера я спросил и получил ответ о том, как заменить значения в кадре данных на основе другого фрейма данных. Но после этого я пришел к na.approx(), а затем решил заменить значения 270.15 на NA и попробовать na.approx() для интерполяции данных. Но возникает вопрос, почему na.approx() не заменяет все NA.

Это то, что я делаю:

  • Прочитайте исходный hdf файл с помощью hdf5load
  • Подмножество фрейма данных (4094x4096)
  • Заменить значение флага с помощью NA

    > sst4[sst4 == 270.15 ] = NA
    
  • Проверить первый столбец (или любой другой)

    > summary(sst4[,1])
    
    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's
    271.3   276.4   285.9   285.5   292.3   302.8  1345.0
    
  • Запустите na.approx

    > sst4=na.approx(sst4,na.rm="FALSE")
    
  • Проверить первый столбец

    > summary(sst4[,1]) 
    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's
    271.3   276.5   286.3   285.9   292.6   302.8   411.0
    

Как вы можете видеть, 411 NA не были удалены. Зачем? Все ли они соответствуют значениям ведущего/конечного столбца?

head(sst4[,1])
[1] NA NA NA NA NA NA
tail(sst4[,1])
[1] NA NA NA NA NA NA

Нужно ли na.approx иметь допустимые значения до и после NA для интерполяции? Нужно ли устанавливать любой другой параметр na.approx?

Большое спасибо

Ответы

Ответ 1

Небольшой, воспроизводимый пример:

library(zoo)
set.seed(1)
m <- matrix(runif(16, 0, 100), nrow = 4)
missing_values <- sample(16, 7)
m[missing_values] <- NA
m
         [,1]     [,2]      [,3]     [,4]
[1,] 26.55087 20.16819 62.911404 68.70228
[2,] 37.21239       NA  6.178627 38.41037
[3,]       NA       NA        NA       NA
[4,] 90.82078 66.07978        NA       NA

na.approx(m)
         [,1]     [,2]      [,3]     [,4]
[1,] 26.55087 20.16819 62.911404 68.70228
[2,] 37.21239 35.47206  6.178627 38.41037
[3,] 64.01658 50.77592        NA       NA
[4,] 90.82078 66.07978        NA       NA

m[4, 4] <- 50
na.approx(m)
         [,1]     [,2]      [,3]     [,4]
[1,] 26.55087 20.16819 62.911404 68.70228
[2,] 37.21239 35.47206  6.178627 38.41037
[3,] 64.01658 50.77592        NA 44.20519
[4,] 90.82078 66.07978        NA 50.00000

Yup, похоже, вам нужны начальные/конечные значения столбцов, которые будут известны, или интерполяция не работает. Можете ли вы угадывать значения для своих границ?

ДРУГОЙ РЕДАКТИРОВАНИЕ: Таким образом, по умолчанию вам нужно знать начальные и конечные значения столбцов. Однако можно получить na.approx, чтобы всегда заполнять пробелы, передавая rule = 2. См. Ответ Феликса. Вы также можете использовать na.fill для предоставления значения по умолчанию, как в комментарии Gabor. Наконец, вы можете интерполировать граничные условия в двух направлениях (см. Ниже) или угадать граничные условия.


EDIT: Еще одна мысль. Поскольку na.approx интерполируется только в столбцах, а ваши данные пространственны, возможно, интерполяция в строках тоже будет полезна. Тогда вы можете взять среднее значение.

na.approx терпит неудачу, когда целые столбцы NA, поэтому мы создаем больший набор данных.

set.seed(1)
m <- matrix(runif(64, 0, 100), nrow = 8)
missing_values <- sample(64, 15)
m[missing_values] <- NA

Запустите na.approx в обоих направлениях.

by_col <- na.approx(m)
by_row <- t(na.approx(t(m)))

Узнайте наилучшее предположение.

default <- 50
best_guess <- ifelse(is.na(by_row), 
  ifelse(
    is.na(by_col), 
    default,              #neither known
    by_col                #only by_col known
  ), 
  ifelse(
    is.na(by_col), 
    by_row,               #only by_row known
    (by_row + by_col) / 2 #both known
  )
)

Ответ 2

na.approx() выполняет функцию approx() только для интерполяции значений, а не экстраполяции их по умолчанию. Однако, как описано на странице справки для approx(), вы можете указать rule = 2, чтобы экстраполировать как постоянное значение ближайшего экстремума. Следуя примеру Ричи Коттона:

na.approx(m, rule = 2)
         [,1]     [,2]      [,3]     [,4]
[1,] 26.55087 20.16819 62.911404 68.70228
[2,] 37.21239 35.47206  6.178627 38.41037
[3,] 64.01658 50.77592  6.178627 38.41037
[4,] 90.82078 66.07978  6.178627 38.41037

Эквивалентно, вы можете использовать "последнее наблюдение переносить вперед" явно.

na.locf(na.approx(m))
## "first observation carry backwards" too:
na.locf(na.locf(na.approx(m)), fromLast = TRUE)