[英]Aggregating while merging two dataframes in R
最終目標是將product_info
中每條記錄的總數量( transact_data$qty
)相加,其中transact_data$productId
存在於product_info
,並且transact_data$date
位於product_info$beg_date
和product_info$end_date
。
數據框如下:
product_info <- data.frame(productId = c("A", "B", "A", "C","C","B"),
old_price = c(0.5,0.10,0.11,0.12,0.3,0.4),
new_price = c(0.7,0.11,0.12,0.11,0.2,0.3),
beg_date = c("2014-05-01", "2014-06-01", "2014-05-01", "2014-06-01","2014-05-01", "2014-06-01"),
end_date = c("2014-05-31", "2014-06-31", "2014-05-31", "2014-06-31","2014-05-31", "2014-06-31"), stringsAsFactors=FALSE)
transact_data <- data.frame(productId=c('A', 'B','A', 'C','A', 'B','C', 'B','A', 'C','A', 'B'),
date=c("2014-05-05", "2014-06-22", "2014-07-05", "2014-08-31","2014-05-03", "2014-02-22",
"2014-05-21", "2014-06-19", "2014-03-09", "2014-06-22","2014-04-03", "2014-07-08"),
qty =c(12,15,5,21,13,17,2,5,11,9,6,4), stringsAsFactors=FALSE)
我的第一步是通過productId合並兩個數據幀:
sku_transact_merge <-merge(x=product_info, y=transact_data, by = c("productId"))
下一步是計算數量總和:
sku_transact_merge$total_qty <- ifelse(sku_transact_merge$date >= sku_transact_merge$beg_date &
sku_transact_merge$date <= sku_transact_merge$end_date,
aggregate(qty ~ productId+beg_date+end_date,
data= sku_transact_merge, sum), 0)
結果不是我想要的,而且我得到了一個錯誤
(list)對象無法強制輸入'double'
任何有關如何正確執行此邏輯的指針都將非常感激!
這可能是使用dplyr()
執行此操作的另一種方法(如果您的數據集很大,這應該是有效的)
library(dplyr)
df = subset(sku_transact_merge, date > beg_date & date < end_date)
df = subset(df, select= -c(date))
out = unique(df %>% group_by(productId,old_price) %>% mutate(qty = sum(qty)))
#> out
#Source: local data frame [6 x 6]
#Groups: productId, old_price
#productId old_price new_price beg_date end_date qty
#1 A 0.50 0.70 2014-05-01 2014-05-31 25
#2 A 0.11 0.12 2014-05-01 2014-05-31 25
#3 B 0.10 0.11 2014-06-01 2014-06-31 20
#4 B 0.40 0.30 2014-06-01 2014-06-31 20
#5 C 0.12 0.11 2014-06-01 2014-06-31 9
#6 C 0.30 0.20 2014-05-01 2014-05-31 2
否則你可以使用data.table
library(data.table)
out = setDT(df)[, list(qtynew = sum(qty)), by = list(productId, old_price)]
#> out
# productId old_price qtynew
#1: A 0.50 25
#2: A 0.11 25
#3: B 0.10 20
#4: B 0.40 20
#5: C 0.12 9
#6: C 0.30 2
一種方法是循環遍歷product_info
的元素,確定transact_data
所有匹配產品並對其數量求和:
sapply(seq(nrow(product_info)), function(x) {
d <- product_info[x,]
sum(transact_data$qty[transact_data$productId == d$productId &
transact_data$date >= d$beg_date &
transact_data$date <= d$end_date])
})
# [1] 25 20 25 9 2 20
如果需要,您可以將其添加為product_info
的新列。
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
每條記錄進行比較。 這三個邏輯矩陣是邏輯AND,以形成表示記錄的哪些組合匹配的最終邏輯矩陣。
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
然后,通過調用arr.ind=T
which()
確定行和列索引為TRUE
。 行索引表示來自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()
將始終返回由分組列排序的結果。 我剛才問這個在aggregate()中是否保證結果將由分組列排序? 。
此外,我剛剛意識到,如果並非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
現在,我們必須構造一個長度等於product_info
中行數的完整向量,並將qty
和(在col
內部)與其對應的索引(內部row
) match()
,而不是取消引用$col
的最后一步。 ,在with()
幫助下。
product_info$total_qty <- with(...,col[match(1:nrow(product_info),row)]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.