Instacart Market Basket Analysis

Instacart Market Basket Analysis

kaggle赛题链接

数据理解

比赛使用的数据仅包含交易数据,不包含浏览数据。主要由以下几张表构成:

  1. 订单表 orders(订单ID,用户ID,所属数据集,该用户的订单序号,订单下单在星期几,订单下单所在小时,距离上一次下单过去的天数):数据粒度为一个订单事实。其中,所属数据集包含三类:a) 先验集:所有用户在历史一段时间内产生的所有订单;b) 训练集:从所有用户中抽出一部分训练用户,在考察周期内产生的所有订单;c) 测试集:除去训练用户外剩下的用户,在考察周期内产生的所有订单。先验集中,每个用户可能包含多个订单。而对于训练集和测试集,两者的用户无交集,且每个用户在各自集合内也只会有一个订单。

  2. 商品表 products(商品ID,商品名称,通道ID,分类ID):数据粒度为一件商品。

  3. 通道表 aisles(通道ID,通道名称):数据粒度为一个通道。这里的通道,就是超市里的通道/走道,每一个通道两侧的商品,通常是一个类别的,而走道上方,往往会有一个标识牌。

  4. 分类表 departments(分类ID,分类名称):数据粒度为一个分类。是比通道更大的分类概念,但二者相互没有确定的包含关系。

  5. 先验集订单商品表 order_products_prior(订单ID,商品ID,加入购物车的次序,是否复购):注意先验集包含所有的用户,这里的数据粒度是历史一段时期内,所有用户购买的所有商品记录。

  6. 训练集订单商品表 order_products_train(订单ID,商品ID,加入购物车次序,是否复购):这里是训练集用户,在考察期内,购买的所有商品记录。上面提过,这个数据集里的每个用户,只会有一个订单,其中包含若干个商品,可能包含也可能不包含复购的商品。

    如果不使用NLP的方法对名称类字段进行处理的话,商品名称、通道名称、分类名称这几个字段是没有用的。在实际项目中,也没有进行相关处理,所以后面这几个字段将略过不谈。

    最终产出的数据,是订单表的测试集中,每个订单所包含的复购商品,也即仅包含复购的测试集订单商品表。由于上面提到了,训练集和测试集实际上是按照用户划分的,所以最终提交的数据,也是测试用户在考察期间内,复购的所有商品。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YaJd25yG-1593220408221)(/home/gavin/Machine/MachineProject/顾客行为预测/数据分析报告/数据分析表.dio (1)].png)

数据加载

prducts_df = pd.read_csv("./data/products.csv")
aisles_df = pd.read_csv("data/aisles.csv")
departments = pd.read_csv("data/departments.csv")
order_products_prior_df = pd.read_csv('data/order_products__prior.csv')
order_products_train_df = pd.read_csv("data/order_products__train.csv")
orders_df = pd.read_csv("data/orders.csv")

统计不同加购订单顺序下的复购率情况

order_products_prior_df["add_to_cart_order_mod"] = order_products_prior_df.add_to_cart_order

# 设置加购件数到达70件以上,则表示为70件
order_products_prior_df.add_to_cart_order_mod[order_products_prior_df.add_to_cart_order_mod>70]=70

### 对加购顺序进行groupy并,计算复购率
groupby_df = order_products_prior_df.groupby(by="add_to_cart_order_mod")["reordered"]
groupby_df = groupby_df.aggregate("mean")
# 可视化
plt.figure(figsize=(12, 6))
groupby_df.plot(c="r", linestyle="dashdot")
plt.ylabel("reordered ratio", fontsize=11)
plt.xlabel("add to cart order", fontsize=11)
plt.title("The recorder ratio of in different order numbers")
plt.grid()
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nK9lOhIm-1593220408223)(output_12_0.png)]

结论:首先放入加购的商品,再一次购买的可能较大(复购率高),越是后面加购的商品,其再一次购买的可能较少。

用户不同大小订单数量分布趋势

# 在订单表中单个用户拥有不止一个订单
orders_df.head()
order_iduser_ideval_setorder_numberorder_doworder_hour_of_daydays_since_prior_order
025393291prior128NaN
123987951prior23715.0
24737471prior331221.0
322547361prior44729.0
44315341prior541528.0
groupby_df = orders_df.groupby(by="user_id")["order_number"].aggregate(np.max)

# 统计不同订单次数下的购买次数
cnt_srs = cnt_srs.order_number.value_counts()

plt.figure(figsize=(18, 6))
sns.barplot(cnt_srs.index, cnt_srs.values
            , color='red'
            , alpha=0.6
           )

plt.xticks(rotation="90")
plt.ylabel("counts", fontsize=12)
plt.xlabel("order numbers", fontsize=12)
plt.title("The counts of different order numbers", fontsize=14)
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j4H1HDTj-1593220408226)(output_19_0.png)]

结论:大多数用户趋向较少的订单,集中处于区间[4, 8]

分析每一笔订单购买商品数据量的分布情况

# 此张表中每一个用户只有一个订单,但订单内可以有很多种商品
order_products_train_df.head()

# 统计一个订单中的商品数量
group_df = order_products_train_df.groupby("order_id")["add_to_cart_order"].aggregate("max").reset_index()
cnt_srs = group_df.add_to_cart_order.value_counts()

plt.figure(figsize=(20, 10))
sns.barplot(cnt_srs.index, cnt_srs.values, color="green", alpha=0.5)
plt.xlabel("Number of products in given order", fontsize=12)
plt.ylabel("Frequency", fontsize= 12)
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YNNOrSP6-1593220408230)(output_25_0.png)]

结论:从图中可以看出大多数用户的订单内的商品都集中在区间[4, 7], 且集中以一个订单5个商品居多.

统计用户在不同时间点(一周内)的购物习惯

plt.figure(figsize=(12, 6))
sns.countplot(x="order_dow", data=orders_df)
plt.xlabel("Day of week")
plt.xticks([i for i in range(7)], ["Sat.", "Sun.", "Mons", "Tues.", "wed.", "Thur.", "Fri."])
plt.title("The frequency in differen day of week")
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Or9dvt3N-1593220408235)(output_29_0.png)]

结论:用户一般习惯集中在周末进行购物,而在周三出现购物的低谷。

研究用户在不同时间点(一天内)的购物习惯

plt.figure(figsize=(12, 6))
sns.countplot(x="order_hour_of_day", data=orders_df, color="blue", alpha=0.6)
plt.xlabel("hour of day")
plt.title("The frequency of order in differen hour of day")
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IzSG1uz5-1593220408237)(output_32_0.png)]

结论:大多数用户偏向与在中午和下午进行购物,也即主要是在白天进行购物

统计用户相隔多长时间加购订单的情况

plt.figure(figsize=(18, 6))
sns.countplot(x="days_since_prior_order", data=orders_df, color="red", alpha=0.5)
plt.ylabel("Count", fontsize=12)
plt.xlabel("day", fontsize=12)
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vf4mbT8m-1593220408240)(output_36_0.png)]

结论:大多数用户在上一次订单之后会在一周之后明显的增加浮动,而在一个月以后出现一个订单回购的小高峰.

不同商品的购买情况

# 商品表
prducts_df.head()
product_idproduct_nameaisle_iddepartment_id
01Chocolate Sandwich Cookies6119
12All-Seasons Salt10413
23Robust Golden Unsweetened Oolong Tea947
34Smart Ones Classic Favorites Mini Rigatoni Wit...381
45Green Chile Anytime Sauce513
# 通道表
aisles_df.head()
aisle_idaisle
01prepared soups salads
12specialty cheeses
23energy granola bars
34instant foods
45marinades meat preparation
# 分类表
departments.head()
department_iddepartment
01frozen
12other
23bakery
34produce
45alcohol
# 订单商品表
order_products_prior_df.head()
order_idproduct_idadd_to_cart_orderreorderedadd_to_cart_order_mod
0233120111
1228985212
229327303
3245918414
4230035505
order_products_prior_df = pd.merge(order_products_prior_df
                                   , prducts_df
                                   , on="product_id", how="left"
                                  )
order_products_prior_df = pd.merge(order_products_prior_df
                              , aisles_df
                              , on="aisle_id"
                              , how="left")
order_products_prior_df = pd.merge(order_products_prior_df
                                   , departments
                                   , on="department_id"
                                   , how = "left"
                                  )

查看不同的商品对于的销售量

cnt_srs = order_products_prior_df.groupby(by="product_name").count()["add_to_cart_order_mod"].reset_index()
cnt_srs.sort_values(by="add_to_cart_order_mod", ascending=False).head(20)
product_nameadd_to_cart_order_mod
3676Banana472565
3471Bag of Organic Bananas379450
31920Organic Strawberries264683
28840Organic Baby Spinach241921
30297Organic Hass Avocado213584
28804Organic Avocado176815
22413Large Lemon152657
42904Strawberries142951
23420Limes140627
32478Organic Whole Milk137905
31363Organic Raspberries137057
32565Organic Yellow Onion113426
30000Organic Garlic109778
32605Organic Zucchini104823
29008Organic Blueberries100060
11630Cucumber Kirby97315
29980Organic Fuji Apple89632
30577Organic Lemon87746
2628Apple Honeycrisp Organic85020
30139Organic Grape Tomatoes84255
# 绘制不同通道下的品类的情况
cnt_srs = order_products_prior_df.aisle.value_counts()

plt.figure(figsize=(12, 6))
sns.barplot(cnt_srs.head(20).index, cnt_srs.head(20).values
            , alpha=0.5
            , color="blue"
           )

plt.xticks(rotation="90")
plt.ylabel("Count")
plt.xlabel("Aisle name")
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bjp8hpkB-1593220408242)(output_52_0.png)]

结论:从图中可以看出购买新鲜蔬菜和水果的订单量较大

绘制不同产品类别之间的所占分数

temp = order_products_prior_df.department.value_counts()
temp.head()
produce       9479291
dairy eggs    5414016
snacks        2887550
beverages     2690129
frozen        2236432
Name: department, dtype: int64
plt.figure(figsize=(8, 8))
plt.pie(temp
        , labels=temp.index
        , autopct="%1.1f%%"
        , startangle=200
       )
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KzS86eFr-1593220408244)(output_56_0.png)]

结论:通过观察可以看出产品和奶制品和鸡蛋类的所占比重较大,可以看出用户偏向与这类商品。

查看不同的大类别下的复购率情况
group_df = order_products_prior_df.groupby("department")["reordered"].mean()
group_df = group_df.reset_index()
group_df.head()
departmentreordered
0alcohol0.569924
1babies0.578971
2bakery0.628141
3beverages0.653460
4breakfast0.560922
plt.figure(figsize=(12, 5))
sns.barplot(group_df.department
            , group_df.reordered
            , alpha=0.8
            , color="blue")

plt.ylabel("reordered ratio", fontsize=12)
plt.title("The reordered ratio in differfent departments", fontsize=13)
plt.xlabel("department", fontsize=12)
plt.xticks(rotation=90)
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1FJBp9HX-1593220408245)(output_62_0.png)]

不同部门下不同通道的复购率情况

group_df = order_products_prior_df.groupby(["department_id", "aisle"])["reordered"].mean()
group_df = group_df.reset_index()
group_df
department_idaislereordered
01frozen appetizers sides0.525557
11frozen breads doughs0.539992
21frozen breakfast0.626221
31frozen dessert0.420777
41frozen juice0.450855
............
12920lunch meat0.606517
13020prepared meals0.619759
13120prepared soups salads0.596597
13220tofu meat alternatives0.607775
13321missing0.395849

134 rows × 3 columns

fig, ax = plt.subplots(figsize=(14, 14))
ax.scatter(group_df.reordered, group_df.department_id, alpha=0.8, color="red")
plt.plot([0.6]*23, np.arange(0, 23), color="red", linestyle="--")

for i, txt in enumerate(group_df.aisle.values):
    ax.annotate(txt, (group_df.reordered[i], group_df.department_id[i])
                , rotation=45
                , color="green"
               )
    plt.xlabel("reordered ratio", fontsize=14)

plt.ylabel("department", fontsize=14)
plt.title("Reorder ration of different aisles", fontsize=20)
plt.yticks(np.arange(1, 22), departments.department)
plt.ylim([0, 22])
plt.xlim([0, 0.9])
plt.grid()
plt.show()

png

结论:通过设置最低的复购率准线,可以查看到每一个部门下的下分类别的复购率情况

用户在不同时间(周内)的复购率情况
order_products_prior_df = pd.merge(order_products_prior_df, orders_df, on="order_id", how="left")

group_df = order_products_prior_df.groupby(by="order_dow")["reordered"].mean()
sns.barplot(group_df.index, group_df.values, color="b", alpha=0.5)
plt.xticks([i for i in range(7)], ["Sat.", "Sun.", "Mons", "Tues.", "wed.", "Thur.", "Fri."])
plt.ylabel("reordered ratio")
plt.xlabel("week")
plt.title("The reordered ratio of different week")
plt.ylim([0.5, 0.7])
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KoDJdAu2-1593220408246)(output_70_0.png)]

用户在不同时间(周内)的复购率情况
group_df = order_products_prior_df.groupby(by="order_hour_of_day")["reordered"].mean()
plt.figure(figsize=(12, 6))
sns.barplot(group_df.index, group_df.values, color="b", alpha=0.8)
plt.ylabel("reordered ratio")
plt.xlabel("hour")
plt.title("The reordered ratio of different hour")
plt.ylim([0.5, 0.7])
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vqUQcMzW-1593220408248)(output_72_0.png)]

group_df= order_products_prior_df.groupby(["order_dow", "order_hour_of_day"])["reordered"].mean().reset_index()
group_df = group_df.pivot("order_dow", "order_hour_of_day", "reordered")
plt.figure(figsize=(12, 6))
sns.heatmap(group_df)
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AEycxavg-1593220408249)(output_75_0.png)]

参考

Kaggle Instacart复购预测竞赛回顾

Kaggle案例:基于Python分析Instacart用户行为

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值