Слияние и агрегирование по нескольким столбцам в r? - PullRequest
0 голосов
/ 30 декабря 2018

У меня есть 2 таблицы.Ниже приведены примеры таблиц и желаемый результат.

Table1:

Start Date  End Date    Country
2017-01-04  2017-01-06   id
2017-02-13  2017-02-15   ng

Table2:

Transaction Date    Country Cost    Product
2017-01-04           id     111        21
2017-01-05           id     200        34
2017-02-14           ng     213        45
2017-02-15           ng     314        32
2017-02-18           ng     515        26

Output:

Start Date  End Date    Country Cost    Product
2017-01-04  2017-01-06  id      311          55
2017-02-13  2017-02-15  ng      527          77

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

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

Это требует нечетких соединений.Ниже приведены 2 примера.

Использование пакетов dplyr и fuzzyjoin:

fuzzy_left_join(df1, df2, 
                c("Country" = "Country",
                  "Start_Date" = "Transaction_Date", 
                  "End_Date" = "Transaction_Date"),
                list(`==`, `<=`,`>=`)) %>% 
  group_by(Country.x, Start_Date, End_Date) %>% 
  summarise(Cost = sum(Cost),
            Product = sum(Product))

# A tibble: 2 x 5
# Groups:   Country.x, Start_Date [?]
  Country.x Start_Date End_Date    Cost Product
  <chr>     <date>     <date>     <int>   <int>
1 id        2017-01-04 2017-01-06   311      55
2 ng        2017-02-13 2017-02-15   527      77

Использование data.table:

library(data.table)
dt1 <- data.table(df1)
dt2 <- data.table(df2)

dt2[dt1, on=.(Country = Country, 
              Transaction_Date >= Start_Date, 
              Transaction_Date <= End_Date), 
    .(Cost = sum(Cost), Product = sum(Product)), 
    by=.EACHI]

data:

df1 <- structure(list(Start_Date = structure(c(17170, 17210), class = "Date"), 
    End_Date = structure(c(17172, 17212), class = "Date"), Country = c("id", 
    "ng")), row.names = c(NA, -2L), class = "data.frame")

df2 <- structure(list(Transaction_Date = structure(c(17170, 17171, 17211, 
17212, 17215), class = "Date"), Country = c("id", "id", "ng", 
"ng", "ng"), Cost = c(111L, 200L, 213L, 314L, 515L), Product = c(21L, 
34L, 45L, 32L, 26L)), row.names = c(NA, -5L), class = "data.frame")
0 голосов
/ 30 декабря 2018

Не уверен, что здесь можно использовать любую из операций merge, но одним из способов использования mapply является подстановка строк на основе условия и получение столбцов sum из Product и Cost.

df1[c("Cost", "Product")] <- t(mapply(function(x, y, z) {
     inds <- df2$Transaction_Date >= x & df2$Transaction_Date <= y & df2$Country == z
     c(sum(df2$Cost[inds]), sum(df2$Product[inds]))
     },df1$Start_Date, df1$End_Date, df1$Country))

df1
#  Start_Date   End_Date Country Cost Product
#1 2017-01-04 2017-01-06      id  311      55
#2 2017-02-13 2017-02-15      ng  527      77
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...