【发布时间】:2019-08-23 00:44:42
【问题描述】:
我有一个数据框,其中一列代表购物篮的索引。对于每个篮子,我都有另一列标识该篮子中的项目。在数据集中查找唯一篮子的最有效方法是什么?
这里是一个使用dplyr的例子:
outer_num <- 10000
tmp_df <-
data.frame(basket_index = rep(1:(8*outer_num), each = 2),
items_purchased = rep(rep(c(1, 1, 2, 2, 1, 1, 3, 3), 2), outer_num))
items_purchased_df <-
data.frame(items_purchased = 1:3,
item_name = c("shampoo", "soap", "conditioner"))
tmp_df_2 <-
tmp_df %>%
inner_join(items_purchased_df) %>%
select(basket_index, items_purchased = item_name)
head(tmp_df_2, 16)
# basket_index items_purchased
# 1 1 shampoo
# 2 1 shampoo
# 3 2 soap
# 4 2 soap
# 5 3 shampoo
# 6 3 shampoo
# 7 4 conditioner
# 8 4 conditioner
# 9 5 shampoo
# 10 5 shampoo
# 11 6 soap
# 12 6 soap
# 13 7 shampoo
# 14 7 shampoo
# 15 8 conditioner
# 16 8 conditioner
在这个例子中,我们看到只有三个独特的购物篮,每个购物篮有两个物品。一般来说,篮子里的物品数量可能不同,可能有也可能没有重复的物品,在某些情况下,篮子中物品的出现顺序很重要。
以下函数产生可接受的输出:
tmp_fn <- function(tmp_df) {
tmp_df %>%
group_by(basket_index) %>%
mutate(collapsed_purchases = paste0(items_purchased, collapse = ',')) %>%
group_by(collapsed_purchases) %>%
filter(basket_index == min(basket_index)) %>%
ungroup
}
这样
tmp_fn(tmp_df_2)
# basket_index items_purchased collapsed_purchases
# <int> <fct> <chr>
# 1 1 shampoo shampoo,shampoo
# 2 1 shampoo shampoo,shampoo
# 3 2 soap soap,soap
# 4 2 soap soap,soap
# 5 4 conditioner conditioner,conditioner
# 6 4 conditioner conditioner,conditioner
这不是非常节省时间。将项目因子转换为整数(并假设这是一个瞬时过程!)将其速度提高了近两个数量级,但即使在这个小数据集上仍然需要半秒:
tmp_df_3 <-
tmp_df_2 %>%
mutate(items_purchased_old = items_purchased,
items_purchased = as.integer(factor(items_purchased)))
microbenchmark::microbenchmark(tmp_fn(tmp_df_2), times = 10)
# Unit: seconds
# expr min lq mean median uq max neval
# tmp_fn(tmp_df_2) 20.6301 20.93541 21.98261 22.24193 22.43473 23.77921 10
microbenchmark::microbenchmark(tmp_fn(tmp_df_3), times = 10)
# Unit: milliseconds
# expr min lq mean median uq max neval
# tmp_fn(tmp_df_3) 348.3901 358.0814 507.7983 363.7639 387.2384 1566.903 10
【问题讨论】: