Значение левого соединения точной даты и, если отсутствует, найти предыдущее значение - PullRequest
2 голосов
/ 01 августа 2020

У меня есть два набора данных (df1 и df2), у которых есть общие столбцы «дата» и «страна», которые используются для left_join наборов данных (особенно столбец «цена» из df2). Если нет точного совпадения (дата и страна), отсутствующие значения (NAs) заполняются значением из предыдущей строки (по стране). Пока это работает достаточно хорошо.

Однако у меня есть проблемы, если нет точного совпадения для первого наблюдения (по стране), потому что тогда невозможно заполнить его предыдущей строкой. В этом случае NA (например, строка 1; 2015-07-18) следует заполнить предыдущим значением из df2, которое содержит наблюдение за 2015-07-15. Важно, чтобы я совпадал с точной датой или предыдущей датой (последнее известное значение), а не с ближайшей датой, которая была бы 20.07.2017.

В итоговой таблице цена на 2015- 07-18 (Великобритания) должно быть 2,5, что является последним известным значением.

Ниже вы найдете текущую таблицу и примерные данные.

   date         country   price
1  2015-07-18   UK        NA  
2  2015-07-20   UK        3.0  
3  2015-07-21   UK        2.7
4  2015-07-22   UK        4.5
5  2015-07-25   UK        4.6
6  2015-07-19   US        1.3
7  2015-07-20   US        2.7
8  2015-07-21   US        3.9
9  2015-07-22   US        2.8
10 2015-07-24   US        2.5
library(dplyr)

date <- c("2015-07-18", "2015-07-20", "2015-07-21", "2015-07-22", "2015-07-25", "2015-07-19", "2015-07-20",
          "2015-07-21", "2015-07-22", "2015-07-24")
country <- c("UK", "UK", "UK", "UK", "UK", "US", "US", "US", "US", "US")

df1 <- cbind.data.frame(date, country)

date <- c("2015-07-15", "2015-07-20", "2015-07-21", "2015-07-22", "2015-07-24", "2015-07-19", "2015-07-20",
          "2015-07-21", "2015-07-22", "2015-07-24")
country <- c("UK", "UK", "UK", "UK", "UK", "US", "US", "US", "US", "US")
price <- c(2.5, 3.0, 2.7, 4.5, 4.6, 1.3, 2.7, 3.9, 2.8, 2.5)

df2 <- cbind.data.frame(date, country, price)

df <- df1 %>%
  left_join(df2, by = c("date", "country"))

df %>%
  group_by(country) %>%
  arrange(date) %>%
  tidyr::fill(price,.direction ="down") %>%
  arrange(country, date) %>%
  ungroup()

Ответы [ 3 ]

2 голосов
/ 02 августа 2020

Вот вариант использования скользящего соединения в data.table (который короче и должен быть намного быстрее):

library(data.table)
setDT(df1)
setDT(df2)
df1[, price := df2[.SD, on=.(country, date), roll=Inf, price]]

вывод:

          date country price
 1: 2015-07-18      UK   2.5
 2: 2015-07-20      UK   3.0
 3: 2015-07-21      UK   2.7
 4: 2015-07-22      UK   4.5
 5: 2015-07-25      UK   4.6
 6: 2015-07-19      US   1.3
 7: 2015-07-20      US   2.7
 8: 2015-07-21      US   3.9
 9: 2015-07-22      US   2.8
10: 2015-07-24      US   2.5

данные:

date <- as.Date(c("2015-07-18", "2015-07-20", "2015-07-21", "2015-07-22", "2015-07-25", "2015-07-19", "2015-07-20",
    "2015-07-21", "2015-07-22", "2015-07-24"))
country <- c("UK", "UK", "UK", "UK", "UK", "US", "US", "US", "US", "US")
df1 <- data.frame(date, country)

date <- as.Date(c("2015-07-15", "2015-07-20", "2015-07-21", "2015-07-22", "2015-07-24", "2015-07-19", "2015-07-20",
    "2015-07-21", "2015-07-22", "2015-07-24"))
country <- c("UK", "UK", "UK", "UK", "UK", "US", "US", "US", "US", "US")
price <- c(2.5, 3.0, 2.7, 4.5, 4.6, 1.3, 2.7, 3.9, 2.8, 2.5)
df2 <- data.frame(date, country, price)

редактировать: искать несколько столбцов:

cols <- c("price", "cost", "revenue") 
df1[, (cols) := df2[.SD, on=.(country, date), roll=Inf, mget(cols)]]
2 голосов
/ 01 августа 2020

Можете попробовать full_join()

df_b <- df1 %>% 
  full_join(df2, by = c("date", "country")) %>% 
  arrange(country, date) %>% 
  group_by(country) %>% 
  mutate(price = ifelse(is.na(price), lag(price), price)) %>% 
  ungroup() %>% 
  filter(date %in% df$date) %>% 
  inner_join(df, by = c("date", "country")) %>% 
  select(-price.y)
# A tibble: 10 x 3
# date       country price.x
# <chr>      <chr>     <dbl>
#   1 2015-07-18 UK          2.5
# 2 2015-07-20 UK          3  
# 3 2015-07-21 UK          2.7
# 4 2015-07-22 UK          4.5
# 5 2015-07-25 UK          4.6
# 6 2015-07-19 US          1.3
# 7 2015-07-20 US          2.7
# 8 2015-07-21 US          3.9
# 9 2015-07-22 US          2.8
# 10 2015-07-24 US          2.5
0 голосов
/ 01 августа 2020

Tho Vu меня опередил, но вот мое решение, которое очень похоже:

full_join(df1,df2) %>% 
    arrange(country, date) %>% 
    mutate(price=ifelse(is.na(price), lag(price), price))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...