product_info$total_qty <- aggregate(col~row,which(outer(product_info$productId,transact_data$productId,`==`)&outer(product_info$beg_date,transact_data$date,`<=`)&outer(product_info$end_date,transact_data$date,`>=`),arr.ind=T),function(x) sum(transact_data$qty[x]))$col;
product_info;
## productId old_price new_price beg_date end_date total_qty
## 1 A 0.50 0.70 2014-05-01 2014-05-31 25
## 2 B 0.10 0.11 2014-06-01 2014-06-31 20
## 3 A 0.11 0.12 2014-05-01 2014-05-31 25
## 4 C 0.12 0.11 2014-06-01 2014-06-31 9
## 5 C 0.30 0.20 2014-05-01 2014-05-31 2
## 6 B 0.40 0.30 2014-06-01 2014-06-31 20
Объяснение
Во-первых, логическая матрица строится для каждого из трех критериев соответствия, используя outer()
сравнивать каждую запись в product_info
с каждой записью в transact_data
. Эти три логические матрицы логически-ANDed вместе, чтобы сформировать конечную логическую матрицу, представляющую, какие комбинации записей совпадают.
outer(product_info$productId,transact_data$productId,`==`)
&outer(product_info$beg_date,transact_data$date,`<=`)
&outer(product_info$end_date,transact_data$date,`>=`)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
## [1,] TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [2,] FALSE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
## [3,] TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [4,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
## [5,] FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
## [6,] FALSE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
Затем строк и столбцов индексов с TRUE
констатированы через вызов which()
с arr.ind=T
. Индексы строк представляют собой совпадающие записи от product_info
(так как они были слева от вызовов outer()
), а индексы столбцов представляют соответствующие записи от transact_data
.
which(...,arr.ind=T)
## row col
## [1,] 1 1
## [2,] 3 1
## [3,] 2 2
## [4,] 6 2
## [5,] 1 5
## [6,] 3 5
## [7,] 5 7
## [8,] 2 8
## [9,] 6 8
## [10,] 4 10
Поскольку мы хотим подвести qty
значения из transact_data
для каждой записи в product_info
, мы можем aggregate()
в col
индексов группирования по row
путем написания пользовательской функции агрегации для индекса transact_data$qty
с col
индексами и sum()
их возвращать одно значение для каждого row
.
aggregate(col~row,...,function(x) sum(transact_data$qty[x]))
## row col
## 1 1 25
## 2 2 20
## 3 3 25
## 4 4 9
## 5 5 2
## 6 6 20
Наконец, мы можем присвоить результат непосредственно product_info$total_qty
завершить решение.
product_info$total_qty <- ...$col;
Я не совсем уверен, если это является гарантией того, что aggregate()
всегда будет возвращать ее результат упорядоченный по столбцу (ы) группировки. Я просто спросил об этом Does aggregate() guarantee that the result will be ordered by the grouping columns?.
Также я понял, что прямое присвоение не удастся, если не все записи в product_info
имели по крайней мере одну соответствующую запись в transact_data
.
Если какая-либо из этих предположений нарушаются, то решение может быть определена следующим образом:
product_info$total_qty <- with(aggregate(col~row,which(outer(product_info$productId,transact_data$productId,`==`)&outer(product_info$beg_date,transact_data$date,`<=`)&outer(product_info$end_date,transact_data$date,`>=`),arr.ind=T),function(x) sum(transact_data$qty[x])),col[match(1:nrow(product_info),row)]);
product_info;
## productId old_price new_price beg_date end_date total_qty
## 1 A 0.50 0.70 2014-05-01 2014-05-31 25
## 2 B 0.10 0.11 2014-06-01 2014-06-31 20
## 3 A 0.11 0.12 2014-05-01 2014-05-31 25
## 4 C 0.12 0.11 2014-06-01 2014-06-31 9
## 5 C 0.30 0.20 2014-05-01 2014-05-31 2
## 6 B 0.40 0.30 2014-06-01 2014-06-31 20
Теперь, вместо конечной стадии разыменования $col
, мы должны построить полный вектор длины, равный числу из строк в product_info
и match()
qty
суммы (которые находятся внутри col
) до соответствующих им индексов (внутри row
), с небольшой помощью от .
product_info$total_qty <- with(...,col[match(1:nrow(product_info),row)]);
Преднамеренно ли вы дублируете записи 'productId, beg_date, end_date' в' product_info' (т.е. 'A, 2014-05-01,2014-05-31' и' B, 2 014-06-01,2014-06-31')? Это приведет к дублированию записей в 'transact_data' путем вызова' merge() 'и, таким образом, суммируется несколько раз во время возможной' sum() ', что я не могу представить, было бы правильно. – bgoldst
Yup тот был предназначенный. – BlackHat
Вы хотите объединить эти дублированные значения 'qty'? Если ваш желаемый результат является уникальной таблицей 'productId, beg_date, end_date', тогда эти дублированные значения qty будут суммированы в одну и ту же выходную запись, которую я все еще не могу представить, будет правильным. Ваш желаемый результат не ясен для меня. – bgoldst