Линейная интерполяция в Oracle с особыми случаями - PullRequest
0 голосов
/ 08 февраля 2019

Чтобы заполнить пропущенные значения, мне нужно интерполировать эти пропущенные значения.

Я получил набор данных, подобный следующему (пример):

Country    Year    Value
A          2000    1.5
A          2001    2.5
A          2002    null
A          2003    4.5
B          2000    null
B          2000    null    
B          2002    5.3
B          2003    6.3
C          2000    1
C          2001    null
C          2002    null
C          2003    4

В результате я бы ожидал:

Country    Year    Value
A          2000    1.5
A          2001    2.5
A          2002    3.5
A          2003    4.5
B          2000    3.3
B          2000    4.3    
B          2002    5.3
B          2003    6.3
C          2000    1
C          2001    2
C          2002    3
C          2003    4

Как я могу интерполировать эти значения с помощью линейной интерполяции.Я действительно не могу прийти к какому-либо представлению о том, как эффективно сделать это в оракуле.

1 Ответ

0 голосов
/ 09 февраля 2019

Oracle имеет различные функции для линейной интерполяции.REGR_SLOPE и REGR_INTERCEPT полезны здесь.

Хитрость в вашем случае заключается в том, что это не линейная регрессия между значением и годом.Это линейная регрессия между значением и номером строки в группе стран.Поэтому нам нужно вычислить этот номер строки, прежде чем мы сможем вычислить интерполяцию.

with input_data (country, year, value) AS (
  SELECT 'A',          2000,    1.5  FROM DUAL UNION ALL
  SELECT 'A',          2001,    2.5  FROM DUAL UNION ALL
  SELECT 'A',          2002,    null FROM DUAL UNION ALL
  SELECT 'A',          2003,    4.5  FROM DUAL UNION ALL
  SELECT 'B',          2000,    null FROM DUAL UNION ALL
  SELECT 'B',          2000,    null FROM DUAL UNION ALL
  SELECT 'B',          2002,    5.3  FROM DUAL UNION ALL
  SELECT 'B',          2003,    6.3  FROM DUAL UNION ALL
  SELECT 'C',          2000,    1    FROM DUAL UNION ALL
  SELECT 'C',          2001,    null FROM DUAL UNION ALL
  SELECT 'C',          2002,    null FROM DUAL UNION ALL
  SELECT 'C',          2003,    4    FROM DUAL
), ordered_input as (   
  SELECT
    i.*,
    row_number() over ( partition by country order by year) rn
  FROM input_data i
)
SELECT 
  country,
  year,
  value, 
  rn * regr_slope(value, rn) over ( partition by country) +
       regr_intercept(value, rn) over ( partition by country)
    as interpolated_value
FROM ordered_input
ORDER BY country, year, rn;
+---------+------+-------+--------------------+
| COUNTRY | YEAR | VALUE | INTERPOLATED_VALUE |
+---------+------+-------+--------------------+
| A       | 2000 |   1.5 |                1.5 |
| A       | 2001 |   2.5 |                2.5 |
| A       | 2002 |       |                3.5 |
| A       | 2003 |   4.5 |                4.5 |
| B       | 2000 |       |                3.3 |
| B       | 2000 |       |                4.3 |
| B       | 2002 |   5.3 |                5.3 |
| B       | 2003 |   6.3 |                6.3 |
| C       | 2000 |     1 |                  1 |
| C       | 2001 |       |                  2 |
| C       | 2002 |       |                  3 |
| C       | 2003 |     4 |                  4 |
+---------+------+-------+--------------------+
...