百货商场用户分析

本文详细探讨了百货商场的用户数据,包括会员信息预处理、订单处理及合并,以及用户画像分析。发现主要消费者为30+~50+岁的女性,偏好化妆护肤和服装类商品,消费高峰集中在周末和下午。RFM分析揭示了用户消费频率和金额,为运营策略提供依据。
摘要由CSDN通过智能技术生成

在此篇文章中,我们将理解数据,数据清洗,数据分析并最后可视化结果。通过这篇文章将一起学习和巩固很多知识。

理解数据

import pandas as pd
import numpy as np
from pandas import DataFrame,Series
import re
import datetime

from pyecharts import options as opts
from pyecharts.charts import Pie,Bar,Grid,Calendar,Tab,Line,Scatter,Gauge
# 会员信息表
customers = pd.read_excel('F:\cumcm2018c1.xlsx')
customers.head()

在这里插入图片描述

# 销售流水表
orders = pd.read_csv('F:\cumcm2018c2.csv')
orders.head()

在这里插入图片描述

print(f'会员信息表中有{customers.shape[0]}条记录,{customers.shape[1]}个字段')
print(f'订单流水表中有{orders.shape[0]}条记录,{orders.shape[1]}个字段')

在这里插入图片描述

数据清洗

会员信息表预处理
# 查看会员表的信息,发现除了会员卡号,其余三个信息都是有空值情况
customers.info()

在这里插入图片描述

# 会员信息表中的用户应该是唯一的,但是表中出现了重复值,把这些重复的会员找出来查看
# 重复项有多少
customers['会员卡号'].duplicated().sum()

在这里插入图片描述

customers[customers['会员卡号'].isin (customers[customers['会员卡号'].duplicated()]['会员卡号'])].sort_values(by=['会员卡号','登记时间'])
# 查看这6个重复的会员信息,从图中可以看出,红色标出的出生日期要不是有明显错误,要不是没填,就认为该条信息是用户随便写的,因为删掉这几条数据。还有两个用户的信息,我们默认保留第一条数据
# 删掉有误数据
customers.drop(index=[66024,34750,63395,119556,92269,99579],inplace=True)

在这里插入图片描述

# 查看表中空值数据占比
customers.isna().mean()

在这里插入图片描述

# 对于会员表中,因为空值数据性别和登记时间空的数据比较少,所以满足出生日期,性别,登记日期全部为空的用户肯定不超过数据的5%,所以我们直接进行删除
# 先复制一份,再操作,不修改原数据
customers_copy=customers.copy()
# customers.isna().sum(axis=1)==3 得到三个字段都是空的行
customers.drop(index = customers[customers.isna().sum(axis=1)==3].index,inplace=True)
# 删除后查看数据情况
print(customers.isnull().mean())
customers.info()

在这里插入图片描述

# 对于出生日期,因为我们需要计算会员的年龄,而目前数据类型是object类型,我们需要转成日期类型
customers['出生日期'].astype('datetime64')
# 或者
customers['出生日期'] = pd.to_datetime(customers['出生日期']) 
# 都是会报错的,因为出生日期这个数据中,有用户随意输入,有不满足条件的数据在内,所以无法通过这两种方法将数据类型转成日期类型

在这里插入图片描述

# 因为我们想知道出生日期,是为了知道这些会员的年龄,好在后面用户画像中了解我们这些用户的年龄,因此我们直接计算出一列作为年龄
def tim(x):
    try:
        return int(datetime.date.today().year)-int(datetime.datetime.fromisoformat(str(x)).year)
    except ValueError:
        pass
customers['年龄'] = customers['出生日期'].apply(tim)
# datetime.datetime.fromisoformat是将字符串转化为日期类型
# datetime.datetime.year得到日期的年份,但是是float类型
# datetime.date.today() 获得今天的日期
customers.head()

在这里插入图片描述

customers.isnull().mean()
# 发现出现有出生日期的数据,但是没有转化成年龄,查看问题原因

在这里插入图片描述

# 查找为什么有出生日期的没有转化为年龄
# 就是出生日期这一列不是空的,但是年龄是空的数据
customers[customers['出生日期'].notna() & customers['年龄'].isna()]
# 发现出现这个现象的原因是部分数据出生日期的格式不正确,所以需要转化数据格式再转化为年龄

在这里插入图片描述

# 调整上面的函数,使格式不正确的出生日期也能转化为年龄
def tim(x):
    try:
        return int(datetime.date.today().year)-int(datetime.datetime.fromisoformat(str('-'.join(str(x).split('/')))).year)
    except ValueError:
        pass
customers['年龄'] = customers['出生日期'].apply(tim)
customers.isnull().mean()

在这里插入图片描述

# 根据年龄查看用户是否存在乱输入信息情况
# 因为正常来消费购物的人,年纪不可能是小于0岁或者大于100岁的,查看用户数情况
customers.query('年龄<0 | 年龄>=100')
# 因为出生日期有问题的消费者比较多,加上出生日期没有的用户数大概有20%的数据有问题,因为出生日期只有在描述用户画像年龄的时候会用到,所以不删除,先保留着

在这里插入图片描述

# 查看登记时间问题数据
# 因为登记时间会员录入时间,一般不应该是有问题的,并且登记时间数据只占所有数据的3%,所以直接删掉
customers.dropna(subset = ['登记时间'],inplace=True)
# 查看等级时间中是否有问题数据
print('最小时间:',customers['登记时间'].min(),'最大时间:',customers['登记时间'].max())
# 将登记时间分成10组,看看登记时间分布
pd.cut(customers['登记时间'],10).value_counts()

在这里插入图片描述

# 发现数据都集中在1990年到2026年,删掉那三个异常值
customers.drop(index = customers.query('登记时间<1990 | 登记时间>"2023-05-09 07:12:00"').index,inplace=True)
# 再次查看登记时间数据,看看是否还有异常数据(因为之前数据分组是分到2026年,但是现在都还没到2026年,若是出现,则表示还是有异常数据)
print(customers['登记时间'].min(),customers['登记时间'].max()) # 得到结果,现在数据正常

在这里插入图片描述

订单流水表预处理
# 查看订单流水表情况
print(orders.isnull().mean())
orders.info()

在这里插入图片描述

# 因为想之后想看看用户的购买偏好,所以手动添加一列type,手动归类商品的类别
def cond(x):
    facial = ['化妆','美白','眼','唇','腮','精华','隔离','面膜','粉底','气垫','口红','乳液','眉','鼻','高光','护肤','睫毛','霜','洁颜','细致','毛孔','保湿','淡斑','修容','遮瑕','膏','啫喱','脸','滋润','肌','胭脂','颊','抗老',
             '喷雾'
             ]
    shoe = ['鞋','靴','高跟','帽']
    clothes = ['衣','裙','裤','女装','男装','服饰']
    perfume = ['香氛','香水','香薰']
    gold = ['黄金','铂金','玉石','宝石','玉','镶嵌','饰品']
    house = ['床','屋','家','木','厨']
    food = ['茶','巧克力','阿胶','酒','糖']
    pattern = '.*['+'|'.join(facial)+'].*'
    pattern1 = '.*['+'|'.join(shoe)+'].*'
    pattern2 = '.*['+'|'.join(clothes)+'].*'
    pattern3 = '.*['+'|'.join(perfume)+'].*'
    pattern4 = '.*['+'|'.join(gold)+'].*'
    pattern5 = '.*['+'|'.join(house)+'].*'
    pattern6 = '.*['+'|'.join(food)+'].*'
    if re.search(pattern,x):
        return '化妆护肤类'
    elif re.search(pattern1,x):
        return '鞋帽类'
    elif re.search(pattern2,x):
        return '服装类'
    elif re.search(pattern3,x):
        return '香水类'
    elif re.search(pattern4,x):
        return '金类玉石'
    elif re.search(pattern5,x):
        return '家装家用'
    elif re.search(pattern6,x):
        return '食品类'
    else:
        return '未知分类'
orders['type'] = orders['商品名称'].apply(cond)
orders.head()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值