Функция векторизации для линейной интерполяции - PullRequest
0 голосов
/ 14 января 2019

У меня есть фрейм данных, который выглядит следующим образом:

# Set RNG
set.seed(33550336)

# Create toy data frame
df <- expand.grid(day = 1:10, dist = seq(0, 100, by = 10))

df1 <- df %>% mutate(region = "Here") 
df2 <- df %>% mutate(region = "There") 
df3 <- df %>% mutate(region = "Everywhere") 

df_ref <- do.call(rbind, list(df1, df2, df3))

df_ref$value <- runif(nrow(df_ref))

# > head(df_ref)
#   day dist region      value
# 1   1    0   Here 0.39413117
# 2   2    0   Here 0.44224203
# 3   3    0   Here 0.44207487
# 4   4    0   Here 0.08007335
# 5   5    0   Here 0.02836093
# 6   6    0   Here 0.94475814

Это представляет эталонный фрейм данных, и я хотел бы сравнить наблюдения с ним. Мои наблюдения взяты в определенный день, который находится в этом фрейме справочных данных (т. Е. day - это целое число от 1 до 10) в регионе, который также находится в этом фрейме данных (т. Е. Here, There или Everywhere), но расстояние (dist) равно , а не , обязательно является целым числом от 0 до 100. Например, мой кадр данных наблюдений (df_obs) может выглядеть следующим образом:

# Observations
df_obs <- data.frame(day = sample(1:10, 3, replace = TRUE), 
                     region = sample(c("Here", "There", "Everywhere")), 
                     dist = runif(3, 0, 100))

# day     region     dist
# 1   6 Everywhere 68.77991
# 2   7      There 57.78280
# 3  10       Here 85.71628

Поскольку dist не является целым числом, я не могу просто найти значение, соответствующее моим наблюдениям, в df_ref, например так:

df_ref %>% filter(day == 6, region == "Everywhere", dist == 68.77991)

Итак, я создал функцию поиска, которая использует функцию линейной интерполяции approx:

lookup <- function(re, di, da){
  # Filter to day and region
  df_tmp <- df_ref %>% filter(region == re, day == da)

  # Approximate answer from distance
  approx(unlist(df_tmp$dist), unlist(df_tmp$value), xout = di)$y
}

Применение этого к моему первому наблюдению дает,

lookup("Everywhere", 68.77991, 6)
#[1] 0.8037013

Тем не менее, когда я применяю функцию с помощью mutate, я получаю другой ответ.

df_obs %>% mutate(ref = lookup(region, dist, day))
#   day     region     dist       ref
# 1   6 Everywhere 68.77991 0.1881132
# 2   7      There 57.78280 0.1755198
# 3  10       Here 85.71628 0.1730285

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

...