Как автоматически интерполировать значения для одного фрейма данных на основе другой справочной таблицы / фрейма данных? - PullRequest
1 голос
/ 10 июня 2019

У меня есть один фрейм данных и одна справочная таблица.Я хочу сравнить df_dat$value с df_lookup$threshold.Если value попадает в диапазон threshold, то создайте новый столбец transfer в df_dat, чтобы его значения были линейно интерполированы из столбца transfer в df_lookup

library(dplyr)

df_lookup <- tribble(
  ~threshold, ~transfer,
  0,   0,
  100,   15,
  200,   35
)
df_lookup
#> # A tibble: 3 x 2
#>   threshold transfer
#>       <dbl>    <dbl>
#> 1         0        0
#> 2       100       15
#> 3       200       35

df_dat <- tribble(
  ~date, ~value,
  "2009-01-01", 0,
  "2009-01-02", 30,
  "2009-01-06", 105,
  "2009-01-09", 150
)
df_dat
#> # A tibble: 4 x 2
#>   date       value
#>   <chr>      <dbl>
#> 1 2009-01-01     0
#> 2 2009-01-02    30
#> 3 2009-01-06   105
#> 4 2009-01-09   150

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

df_dat %>% 
  mutate(transfer = case_when(value > 0 & value < 100 ~ 0 + (value - 0)*(15 - 0)/(100 - 0),
                              value >= 100 & value < 200 ~ 15 + (value - 100)*(35 - 15)/(200 - 100),
                              TRUE ~ 0)
  )
#> # A tibble: 4 x 3
#>   date       value transfer
#>   <chr>      <dbl>    <dbl>
#> 1 2009-01-01     0      0  
#> 2 2009-01-02    30      4.5
#> 3 2009-01-06   105     16  
#> 4 2009-01-09   150     25

Ответы [ 2 ]

3 голосов
/ 10 июня 2019

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

df_dat %>% mutate(transfer = with(df_lookup, approx(threshold, transfer, value))$y)
## A tibble: 4 x 3
#  date       value transfer
#  <chr>      <dbl>    <dbl>
#1 2009-01-01     0      0
#2 2009-01-02    30      4.5
#3 2009-01-06   105     16
#4 2009-01-09   150     25
2 голосов
/ 11 июня 2019

Другой вариант с использованием roll:

df_lookup[, m := (transfer - shift(transfer, -1L)) / (threshold - shift(threshold, -1L))]

df_dat[, tx := 
    df_lookup[df_dat, on=c("threshold"="value"), roll=Inf, 
        x.m * (i.value - x.threshold) + x.transfer]
]

данные:

library(data.table)
df_lookup <- fread("threshold, transfer
0,   0
100,   15
200,   35")

df_dat <- fread('date, value
"2009-01-01", 0
"2009-01-02", 30
"2009-01-06", 105
"2009-01-09", 150')
...