Есть ли функция R для сопоставления индекса даты? - PullRequest
1 голос
/ 16 апреля 2020

У меня есть набор данных с большим количеством стран и валютных данных, например:

   iso   date        SPOT
   <chr> <date>     <dbl>
 1 AUD   2000-01-03 0.658
 2 AUD   2000-01-04 0.655
 3 AUD   2000-01-05 0.658
 4 AUD   2000-01-06 0.653
 5 AUD   2000-01-07 0.655
 6 AUD   2000-01-10 0.656
 7 AUD   2000-01-11 0.658
 8 AUD   2000-01-12 0.659
 9 AUD   2000-01-13 0.668
10 AUD   2000-01-14 0.666

, и я хочу создать точный индекс даты, в котором данные для каждого сопоставляются с днем ​​одного год a go, поэтому отображение данных в «LAG1» выглядит следующим образом, где LAG1 = дата - годы (1):

   iso   date        SPOT LAG1      
   <chr> <date>     <dbl> <date>    
 1 AUD   2000-01-03 0.658 1999-01-03
 2 AUD   2000-01-04 0.655 1999-01-04
 3 AUD   2000-01-05 0.658 1999-01-05
 4 AUD   2000-01-06 0.653 1999-01-06
 5 AUD   2000-01-07 0.655 1999-01-07
 6 AUD   2000-01-10 0.656 1999-01-10
 7 AUD   2000-01-11 0.658 1999-01-11
 8 AUD   2000-01-12 0.659 1999-01-12
 9 AUD   2000-01-13 0.668 1999-01-13
10 AUD   2000-01-14 0.666 1999-01-14

Это было мое решение:

df %>% 
  mutate(LAG1=date-years(1)) %>%
  select(iso,LAG1=date,LAG1_SPOT=SPOT) %>% 
  right_join(.,df,by=c("iso", "LAG1")) %>% as_tibble()

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

Есть ли лучший способ сделать это?

1 Ответ

1 голос
/ 16 апреля 2020

Я думаю, что ваше намерение слиться / присоединиться - правильный путь к go. На самом деле, это «правильно», потому что естественно будет лучше справляться с аномалиями данных. Я также думаю, что в вашем коде есть пара небольших ошибок logi c.

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

library(dplyr)
library(lubridate)
dates <- seq.Date(as.Date("2020-03-15"), by = "day", length.out = 5)
df <- tibble(
  iso = rep(c("AUD", "USD"), each = 10),
  date = rep(c(dates - years(1), dates), times = 2),
  SPOT = 1:20
)
# data missingness
df <- df[-3,]
# repeated date
df$date[12] <- df$date[13]
df
# # A tibble: 19 x 3
#    iso   date        SPOT
#    <chr> <date>     <int>
#  1 AUD   2019-03-15     1
#  2 AUD   2019-03-16     2
#  3 AUD   2019-03-18     4
#  4 AUD   2019-03-19     5
#  5 AUD   2020-03-15     6
#  6 AUD   2020-03-16     7
#  7 AUD   2020-03-17     8
#  8 AUD   2020-03-18     9
#  9 AUD   2020-03-19    10
# 10 USD   2019-03-15    11
# 11 USD   2019-03-16    12
# 12 USD   2019-03-18    13
# 13 USD   2019-03-18    14
# 14 USD   2019-03-19    15
# 15 USD   2020-03-15    16
# 16 USD   2020-03-16    17
# 17 USD   2020-03-17    18
# 18 USD   2020-03-18    19
# 19 USD   2020-03-19    20

Используя ваш код сверху, мы видим это:

df %>%
  mutate(date = date - years(1)) %>%
  rename(LAG1_SPOT = SPOT) %>%
  right_join(., df, by = c("iso", "date"))
# # A tibble: 19 x 4
#    iso   date       LAG1_SPOT  SPOT
#    <chr> <date>         <int> <int>
#  1 AUD   2019-03-15         6     1
#  2 AUD   2019-03-16         7     2
#  3 AUD   2019-03-18         9     4
#  4 AUD   2019-03-19        10     5
#  5 AUD   2020-03-15        NA     6
#  6 AUD   2020-03-16        NA     7
#  7 AUD   2020-03-17        NA     8
#  8 AUD   2020-03-18        NA     9
#  9 AUD   2020-03-19        NA    10
# 10 USD   2019-03-15        16    11
# 11 USD   2019-03-16        17    12
# 12 USD   2019-03-18        19    13
# 13 USD   2019-03-18        19    14
# 14 USD   2019-03-19        20    15
# 15 USD   2020-03-15        NA    16
# 16 USD   2020-03-16        NA    17
# 17 USD   2020-03-17        NA    18
# 18 USD   2020-03-18        NA    19
# 19 USD   2020-03-19        NA    20

Поскольку я полагаю, что вы намерены сравнить данные за этот год с данными за прошлый год, то вышеизложенное показывает, что мы их сопоставили, но дата ссылки - прошлогодняя. Я предлагаю вам использовать +:

df %>%
  mutate(date = date + years(1)) %>%
  rename(LAG1_SPOT = SPOT) %>%
  right_join(., df, by = c("iso", "date"))
# # A tibble: 20 x 4
#    iso   date       LAG1_SPOT  SPOT
#    <chr> <date>         <int> <int>
#  1 AUD   2019-03-15        NA     1
#  2 AUD   2019-03-16        NA     2
#  3 AUD   2019-03-18        NA     4
#  4 AUD   2019-03-19        NA     5
#  5 AUD   2020-03-15         1     6
#  6 AUD   2020-03-16         2     7
#  7 AUD   2020-03-17        NA     8
#  8 AUD   2020-03-18         4     9
#  9 AUD   2020-03-19         5    10
# 10 USD   2019-03-15        NA    11
# 11 USD   2019-03-16        NA    12
# 12 USD   2019-03-18        NA    13
# 13 USD   2019-03-18        NA    14
# 14 USD   2019-03-19        NA    15
# 15 USD   2020-03-15        11    16
# 16 USD   2020-03-16        12    17
# 17 USD   2020-03-17        NA    18
# 18 USD   2020-03-18        13    19
# 19 USD   2020-03-18        14    19
# 20 USD   2020-03-19        15    20

Это также показывает, как будут отображаться аномалии данных. Во-первых, в AUD мы видим, что в 03-17 отсутствуют данные за прошлый год, поэтому нам не с чем сравнить спот 8 с. Это просто тот факт, что нам не хватает данных. Это неизбежно, но lag здесь даст нам данные, вероятно, с неправильной даты. Во-вторых, мы видим, что наши двойные данные (системы сбора данных несовершенны!), Теперь у нас есть две строки для USD на 2020-03-18, что, безусловно, подозрительно (но выходит за рамки вашего вопроса). Но мы сравнили оба значения 2019 года с одним значением 2020 года.

Если аномалии данных никогда не появляются в ваших данных, я все еще думаю, что join является правильным методом для решения этой проблемы, как будто есть когда lag найдет неправильную строку (високосные годы?), вы никогда не узнаете, что она не удалась: вы получите данные и будете использовать их без указания.

Кстати: если вы просто уменьшая четыре строки кода, это совершенно эквивалентно:

transmute(df, iso, date = date + years(1), LAG1_SPOT = SPOT) %>%
  right_join(., df, by = c("iso", "date"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...