Интерполировать значения в столбце данных на месте, используя dplyr - PullRequest
0 голосов
/ 16 января 2020

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

Хотя я знаю, что могу сделать это с помощью al oop, я ' Я хотел бы сделать это, используя dplyr (для согласованности и читабельности и потому, что я знаю, что циклы ужасно уродливы в R ).

Вот пример того, что я пытаюсь сделать:

data.raw <- tibble(x=c(66, 67, 68, 69, 70, 72, 73, 75, 93), 
                   S=c(0.11755811, 0.11648940, 0.11542069, 0.11434199, 
                       0.11218459, 0.10996312, 0.10884104, 0.10767071, 
                       0.09228918))
# As you can see, there are some "holes" in the data. For example, the value
# for x = 71 is missing.

# I've created a new dataframe with all the values for x as this:
data.proc <- tibble(x=66:(data.raw %>% select(x) %>% pull() %>% max)) %>% 
  left_join(data.raw, by='x')

# Here's my non optimal 'for' solution:
for(x_ in data.proc$x) {
  if(is.na(data.proc[data.proc$x == x_, 'S'])) {
    # Get min and max values for x
    x.0 <- max(data.proc[data.proc$x < x_, 'x'])
    x.1 <- min(data.proc[data.proc$x > x_, 'x'])
    S.0 <- data.proc[data.proc$x == x.0, 'S']
    S.1 <- data.proc[data.proc$x == x.1, 'S']
    # Calculate the slope
    m <- (S.1 - S.0) / (x.1 - x.0)
    # Set the new value
    data.proc[data.proc$x == x_, 'S'] <- m * (x_ - x.0) + S.0
  }
}

Итак, мой вопрос: есть ли способ сделать это напрямую с dplyr? До сих пор ми гугл-фу меня подводит: (

Ответы [ 2 ]

2 голосов
/ 16 января 2020

Вы можете использовать approx

library(tidyverse)
left_join(tibble(x = seq(min(data.raw$x), max(data.raw$x))), data.raw) %>%
    mutate(S = if_else(is.na(S), approx(x, S, x)$y, S))
## A tibble: 28 x 2
#       x     S
#   <dbl> <dbl>
# 1    66 0.118
# 2    67 0.116
# 3    68 0.115
# 4    69 0.114
# 5    70 0.112
# 6    71 0.111
# 7    72 0.110
# 8    73 0.109
# 9    74 0.108
#10    75 0.108
## … with 18 more rows

Предполагается, что (1) x - это набор целых значений от min(data.raw$x) до max(data.raw$x), и (2) вы хотите только inter polate значения в этом интервале (не extra polate, в случае, если вы хотите использовать что-то вроде lm).

1 голос
/ 16 января 2020

Мы можем использовать complete из tidyr для заполнения отсутствующих значений в x na.approx из zoo для интерполяции NA значений в S.

library(dplyr)
library(tidyr)

data.raw %>% complete(x = seq(min(x), max(x))) %>% mutate(S = zoo::na.approx(S))

# A tibble: 28 x 2
#      x     S
#   <dbl> <dbl>
# 1    66 0.118
# 2    67 0.116
# 3    68 0.115
# 4    69 0.114
# 5    70 0.112
# 6    71 0.111
# 7    72 0.110
# 8    73 0.109
# 9    74 0.108
#10    75 0.108
# … with 18 more rows
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...