R - объединение двух таблиц и вычисление переводов между переменными - PullRequest
5 голосов
/ 25 сентября 2019

У меня есть два кадра данных в R

Что я пытаюсь сделать, это для каждого магазина в Sales df, если продукт находится в столбце «Product» в Transfer df, тогда продажи продуктабудет перенесено в Продукт в столбце «Replacement_Product».

Правило передачи: если оба перехода к товару находятся в магазине, то 90% продаж продукта «from product» распределяется поровну на два продукта «replace_product».».Если в магазине есть только один «запасной продукт», то переносится 80% продаж «из продукта».

Я застреваю в том, что это не всегда перевод один на один.Используя Магазин 1 в качестве примера, продукт A переносится как в B, так и в C, следовательно, 90% от продажи 200 из A будет в равной степени перенесено в B и C, т.е.X переводит в Y и Z в таблице переносов, но в магазине 1 есть только элементы X и Y, в этом случае 80% X будет добавлено к Y.

Если это был один к одному Iможет присоединиться и затем выполнить расчеты, но необходимость проверить, есть ли в магазине 0, 1 или 2 предмета для передачи, а затем процент передачи зависит от того, сколько предметов для перевода застряло у меня при запуске.

Продажи df:

+----------+-------+-------+
| Product  | Store | Sales |
+----------+-------+-------+
| A        |     1 |   200 |
| B        |     1 |   100 |
| C        |     1 |   200 |
| X        |     1 |   400 |
| Y        |     1 |   350 |
| A        |     2 |  1000 |
| B        |     2 |  1000 |
| C        |     2 |   600 |
| X        |     2 |   700 |
| Y        |     2 |   800 |
| Z        |     2 |   400 |
| A        |     3 |  1000 |
| X        |     3 |   500 |
| Z        |     3 |   400 |
+----------+-------+-------+

Передача df:
Список продуктов и их заменяющих продуктов

+---------+---------------------+
| Product | Replacement_Product |
+---------+---------------------+
| A       | B                   |
| A       | C                   |
| X       | Y                   |
| X       | Z                   |
+---------+---------------------+

Таблица вывода:

+----------+-------+-------+
| Product  | Store | Sales |
+----------+-------+-------+
| B        |     1 |   190 |
| C        |     1 |   290 |
| Y        |     1 |   670 |
| B        |     2 |  1450 |
| C        |     2 |  1050 |
| Y        |     2 |  1115 |
| Z        |     2 |   715 |
| Z        |     3 |   800 |
+----------+-------+-------+

Что япопробовал:

test <- sqldf("select a.*, b.Replacement_Product from Sales a 
left join Transfer b on a.Product = b.Product
where a.Product in ('A','B')")

Как только у меня будет таблица с Продуктом и их переносами, я собираюсь снова присоединиться к нему в Replacement_Product и Store, чтобы получить Продажи, а затем, основываясь на 0, я могу сделатьa, если заявление для расчета новых продаж, а затем я удаляю A, B и т. д. Однакотак как я делаю это, он не выглядит масштабируемым, если таблица большая, и я не могу указать, как удаляется Продукт.

Вот продажи df:

structure(list(Product = structure(c(1L, 2L, 3L, 4L, 5L, 1L, 
2L, 3L, 4L, 5L, 6L, 1L, 4L, 6L), .Label = c("A", "B", "C", "X", 
"Y", "Z"), class = "factor"), Store = c(1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L), Sales = c(200L, 100L, 200L, 
400L, 350L, 1000L, 1000L, 600L, 700L, 800L, 400L, 1000L, 500L, 
400L)), .Names = c("Product", "Store", "Sales"), class = "data.frame", row.names = c(NA, 
-14L))

Transfer df:

structure(list(Product = structure(c(1L, 1L, 2L, 2L), .Label = c("A", 
"X"), class = "factor"), Replacement_Product = structure(1:4, .Label = c("B", 
"C", "Y", "Z"), class = "factor")), .Names = c("Product", "Replacement_Product"
), class = "data.frame", row.names = c(NA, -4L))

Ответы [ 2 ]

2 голосов
/ 25 сентября 2019

Вероятно, есть более краткий способ, но здесь начнем с использования dplyr.

library(dplyr)
sales %>%
  inner_join(transfer) %>%
  inner_join(sales %>% select(Replacement_Product = Product, Store)) %>%
  add_count(Product, Store) %>%
  mutate(Sales_trans = if_else(n == 2, Sales * 0.9 / 2, Sales * 0.8)) %>%
  left_join(sales, by = c("Replacement_Product" = "Product", "Store")) %>%
  mutate(total = Sales_trans + Sales.y) %>%
  select(Product = Replacement_Product, Store, total)

  Product Store total
  <chr>   <int> <dbl>
1 B           1   190
2 C           1   290
3 Y           1   670
4 B           2  1450
5 C           2  1050
6 Y           2  1115
7 Z           2   715
8 Z           3   800
1 голос
/ 25 сентября 2019

Вот плотный way:

library(data.table)
setDT(sales)
setDT(transfer)

merged <- transfer[sales, on = .(Product), allow.cartesian = T]

merged[merged
         , on = .(Product = Replacement_Product, Store)
         , .(x.Product, i.Product, Store, Sales, i.Sales)
         , nomatch = 0L
         ][, Total_Sales := Sales + ifelse(.N == 2, 0.9 * 0.5 * i.Sales, 0.8 * i.Sales)
           , by = .(i.Product, Store)
           ][, .(Product = x.Product, Store, Total_Sales)]

   Product Store Total_Sales
1:       B     1         190
2:       C     1         290
3:       Y     1         670
4:       B     2        1450
5:       C     2        1050
6:       Y     2        1115
7:       Z     2         715
8:       Z     3         800
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...