当前位置: 首页 > news >正文

机器学习/数据分析案例---学生消费行为分析,“泰迪杯赛题”

前言

  • 这是一道“泰迪杯“杯的数据分析赛题,对于我现阶段,难度还是很大的,参考了不少资料做完的,这一次我再一次意思到了自己的实力🌵🌵🌵🌵🌵🌵;

  • 熟练使用Pandas、机器学习库是基础😢😢😢😢😢😢😢;

  • 我感觉数据分析具有很强的业务性,很适合学生去学习,从而了解业务;

  • 这一次代码量很大,观看起来应该都很麻烦,但是总体坐下来对数据分析逻辑也有了不小帮助;

  • 欢迎收藏 + 关注,本人将会持续更新,未来将每周至少更新一篇机器学习、深度学习案例

思路分析

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Part1 数据导入与预处理

任务1.1

  • 对数据data1、data2、data3中数据进行探究,理解字段含义
  • 处理缺失值和异常值
  • 对特殊字段,进行初步分析
  • 处理后数据重新保存成.csv文件
# 导入库
import numpy as np 
import pandas as pd 
import os # 读取数据
data1 = pd.read_csv("data1.csv", encoding="gbk")
data2 = pd.read_csv("data2.csv", encoding="gbk")
data3 = pd.read_csv("data3.csv", encoding="gbk")

data1的处理

# data1的展示
data1.head(3)
IndexCardNoSexMajorAccessCardNo
0118000118国际金融19762330
1218000218国际金融20521594
2318000318国际金融20513946
# 查看数据大小
data1.shape

输出:

(4341, 5)
# 标题栏从新命名,命名为中文
data1.columns = ['序号', '校园卡号', '性别', '专业名称', '门禁卡号']
# 效果输出
data1.head(3)
序号校园卡号性别专业名称门禁卡号
0118000118国际金融19762330
1218000218国际金融20521594
2318000318国际金融20513946
# 查看数据类型,看是否有缺失值,方便后续处理
data1.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4341 entries, 0 to 4340
Data columns (total 5 columns):#   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 0   序号      4341 non-null   int64 1   校园卡号    4341 non-null   int64 2   性别      4341 non-null   object3   专业名称    4341 non-null   object4   门禁卡号    4341 non-null   int64 
dtypes: int64(3), object(2)
memory usage: 169.7+ KB
# 没有缺失值,data1数据主要就是记录学生信息,故没有异常值
data1.to_csv("./task1_1_1.csv", index=False, encoding='utf-8-sig')

data2的处理

# 查看前几条数据
data2.head(3)
IndexCardNoPeoNoDateMoneyFundMoneySurplusCardCountTypeTermNoTermSerNoconOperNoOperNoDept
0117342773181316201813162019/4/20 20:173.00.0186.1818消费49NaNNaN235第一食堂
1117344766181316201813162019/4/20 8:470.50.0199.5814消费63NaNNaN27第二食堂
2117346258181316201813162019/4/22 7:270.50.0183.1820消费63NaNNaN27第二食堂
# 查看数据维度,大小
data2.shape  # 数据量很大

输出:

(519367, 14)
# 表头修改,方便深入理解
data2.columns = ['流水号', '校园卡号', '校园卡编号', '消费时间', '消费金额', '存储金额', '余额', '消费次数', '消费类型', '消费项目编码', '消费项目序列号', '消费操作编码', '操作编码', '消费地点']
# 查看数据
data2.head(3)
流水号校园卡号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码消费项目序列号消费操作编码操作编码消费地点
0117342773181316201813162019/4/20 20:173.00.0186.1818消费49NaNNaN235第一食堂
1117344766181316201813162019/4/20 8:470.50.0199.5814消费63NaNNaN27第二食堂
2117346258181316201813162019/4/22 7:270.50.0183.1820消费63NaNNaN27第二食堂
# data2中消费时间数据进行格式转换,采用自动推断格式
data2.loc[:, '消费时间'] = pd.to_datetime(data2.loc[:, '消费时间'], format='mixed', errors='coerce')
data2.head(3)
流水号校园卡号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码消费项目序列号消费操作编码操作编码消费地点
0117342773181316201813162019-04-20 20:17:003.00.0186.1818消费49NaNNaN235第一食堂
1117344766181316201813162019-04-20 08:47:000.50.0199.5814消费63NaNNaN27第二食堂
2117346258181316201813162019-04-22 07:27:000.50.0183.1820消费63NaNNaN27第二食堂
# 查看缺失值占比
data2.apply(lambda x : sum(x.isnull()) / len(x), axis=0)

输出:

流水号        0.000000
校园卡号       0.000000
校园卡编号      0.000000
消费时间       0.000000
消费金额       0.000000
存储金额       0.000000
余额         0.000000
消费次数       0.000000
消费类型       0.000000
消费项目编码     0.000000
消费项目序列号    0.986020
消费操作编码     0.999517
操作编码       0.000000
消费地点       0.000000
dtype: float64

消费项目序列号和操作编码缺失值过多,故删除

data2_new = data2[['流水号', '校园卡号', '校园卡编号', '消费时间', '消费金额', '存储金额', '余额', '消费次数', '消费类型', '消费项目编码', '操作编码', '消费地点']]
data2_new.head(3)
流水号校园卡号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
0117342773181316201813162019-04-20 20:17:003.00.0186.1818消费49235第一食堂
1117344766181316201813162019-04-20 08:47:000.50.0199.5814消费6327第二食堂
2117346258181316201813162019-04-22 07:27:000.50.0183.1820消费6327第二食堂
# 统计消费地点出现的频次,为了后面分析消费行为
data2['消费地点'].value_counts(dropna=False)

输出:

消费地点
第二食堂      154873
第五食堂      117615
第一食堂       62090
第四食堂       60841
第三食堂       52103
好利来食品店     31781
财务处        18295
红太阳超市      12942
水电缴费处       3388
教师食堂        2145
医务室          794
第二图书馆        376
第一图书馆        291
工商系部         197
自然科学书库       195
财务部          170
第七教学楼        165
基础课部         133
艺术设计学院       131
第六教学楼        130
人文社科         109
第二教学楼         99
第五教学楼         99
飞凤轩宿管办        86
机电系           78
第四教学楼         56
第三教学楼         52
宿管办           47
青鸾苑宿管办        25
财经系           23
第一教学楼         23
外语系           12
旅游系            3
Name: count, dtype: int64
# 统计量分析,选取相关的数据特征
data2[['消费金额', '存储金额', '余额', '消费次数']].describe()
消费金额存储金额余额消费次数
count519367.000000519367.000000519367.000000519367.000000
mean4.0872793.94975878.4955171016.565421
std8.90028434.329017121.537938812.625096
min0.0000000.0000000.0000001.000000
25%1.2000000.00000034.100000504.000000
50%3.0000000.00000064.500000749.000000
75%6.0000000.00000099.3900001422.000000
max900.0000009800.0000009903.61000014575.000000
# 存储新的cvs文件中
data2_new.to_csv('./task1_1_2.csv', index=False, encoding='utf-8-sig')

data3处理

# 查看data3数据
data3.head(3)
IndexAccessCardNoDateAddressAccessDescribe
01330906255588802019/4/1 0:00第六教学楼[进门]1允许通过
11330907184131432019/4/1 0:02第六教学楼[出门]1允许通过
21331384116427522019/4/1 0:00飞凤轩[进门]1允许通过
# 查看维度
data3.shape

输出:

(43156, 6)
# 重新命名
data3.columns = ['序号', '门禁卡号', '进出时间', '进出地点', '是否通过', '描述']
data3.head(3)
序号门禁卡号进出时间进出地点是否通过描述
01330906255588802019/4/1 0:00第六教学楼[进门]1允许通过
11330907184131432019/4/1 0:02第六教学楼[出门]1允许通过
21331384116427522019/4/1 0:00飞凤轩[进门]1允许通过
# 查看数据类型
data3.dtypes

输出:

序号       int64
门禁卡号     int64
进出时间    object
进出地点    object
是否通过     int64
描述      object
dtype: object
# 修改时间代码
data3['进出时间'] = pd.to_datetime(data3.loc[:, '进出时间'], format='mixed', errors='coerce')
# 查看
data3.head(3)
序号门禁卡号进出时间进出地点是否通过描述
01330906255588802019-04-01 00:00:00第六教学楼[进门]1允许通过
11330907184131432019-04-01 00:02:00第六教学楼[出门]1允许通过
21331384116427522019-04-01 00:00:00飞凤轩[进门]1允许通过
# 统计出现各地点的频次
data3['进出地点'].value_counts(dropna=False)
进出地点
飞凤轩[进门]      10689
飞凤轩[出门]      10397
第六教学楼[进门]     7713
第六教学楼[出门]     7217
青鸾苑[出门]       3318
青鸾苑[进门]       2787
第七教学楼[进门]      449
第五教学楼[进门]      250
第五教学楼[出门]      222
第七教学楼[出门]      114
Name: count, dtype: int64
# 统计进出成功
data3['是否通过'].value_counts(dropna=False)

输出:

是否通过
1    41749
0     1407
Name: count, dtype: int64
# 0,代表没有进出,故删除
print('删除异常值之前: ',  data3.shape)
data3 = data3[data3.loc[:, '是否通过'] != 0]
print('删除异常值之后: ', data3.shape)
删除异常值之前:  (43156, 6)
删除异常值之后:  (41749, 6)
# 存储
data3.to_csv('./task1_1_3.csv', index=False, encoding='utf-8-sig')

任务1.2

  • 分别对data1个人信息与data2消费记录,data3的门禁出入建立关联
data1 = pd.read_csv("./task1_1_1.csv")
data2 = pd.read_csv("./task1_1_2.csv")
data3 = pd.read_csv("./task1_1_3.csv")data1.head(3)
序号校园卡号性别专业名称门禁卡号
0118000118国际金融19762330
1218000218国际金融20521594
2318000318国际金融20513946
data2.head(3)
流水号校园卡号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
0117342773181316201813162019-04-20 20:17:003.00.0186.1818消费49235第一食堂
1117344766181316201813162019-04-20 08:47:000.50.0199.5814消费6327第二食堂
2117346258181316201813162019-04-22 07:27:000.50.0183.1820消费6327第二食堂
data3.head(3)
序号门禁卡号进出时间进出地点是否通过描述
01330906255588802019-04-01 00:00:00第六教学楼[进门]1允许通过
11330907184131432019-04-01 00:02:00第六教学楼[出门]1允许通过
21331384116427522019-04-01 00:00:00飞凤轩[进门]1允许通过
# data1 和 data2 进行合并
data1_merge_data2 = pd.merge(data1, data2, how='left', left_on='校园卡号', right_on='校园卡号')
data1_merge_data2.shape

输出:

(242152, 16)
data1_merge_data2.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
0118000118国际金融19762330117331517.020181.02019-04-21 18:30:007.00.028.4206.0消费41.0249.0第四食堂
1118000118国际金融19762330117341866.020181.02019-04-22 09:40:003.50.024.9207.0消费19.0236.0第一食堂
2118000118国际金融19762330117154618.020181.02019-04-10 16:42:0011.00.02.7189.0消费82.018.0第四食堂
# 合并后数据分析,检查数据确实
data1_merge_data2.apply(lambda x : sum(x.isnull()) / len(x), axis=0)
序号        0.000000
校园卡号      0.000000
性别        0.000000
专业名称      0.000000
门禁卡号      0.000000
流水号       0.004431
校园卡编号     0.004431
消费时间      0.004431
消费金额      0.004431
存储金额      0.004431
余额        0.004431
消费次数      0.004431
消费类型      0.004431
消费项目编码    0.004431
操作编码      0.004431
消费地点      0.004431
dtype: float64

缺失值占比很小,数据量足够大,故删除

print('删除前缺失值: ', data1_merge_data2.shape)
data1_merge_data2 = data1_merge_data2.dropna(subset=['消费地点'], how='any')
print('删除缺失值后:', data1_merge_data2.shape)
删除前缺失值:  (242152, 16)
删除缺失值后: (241079, 16)
# 合并后数据进行存储
data1_merge_data2.to_csv('./task1_2_1.csv', index=False, encoding='utf-8-sig')
# 合并data1和data3数据
data1_merge_data3 = pd.merge(data1, data3, how='left', left_on='门禁卡号', right_on='门禁卡号')
data1_merge_data3.head()
序号_x校园卡号性别专业名称门禁卡号序号_y进出时间进出地点是否通过描述
0118000118国际金融19762330NaNNaNNaNNaNNaN
1218000218国际金融20521594NaNNaNNaNNaNNaN
2318000318国际金融20513946NaNNaNNaNNaNNaN
3418000418国际金融20018058NaNNaNNaNNaNNaN
4518000518国际金融20945770NaNNaNNaNNaNNaN
# 查看缺失值占比
data1_merge_data3.apply(lambda x : sum(x.isnull()) / len(x), axis=0)
序号_x    0.000000
校园卡号    0.000000
性别      0.000000
专业名称    0.000000
门禁卡号    0.000000
序号_y    0.157723
进出时间    0.157723
进出地点    0.157723
是否通过    0.157723
描述      0.157723
dtype: float64
# 删除
print('删除缺失值前: ',data1_merge_data3.shape)
data1_merge_data3 = data1_merge_data3.dropna(subset=['进出地点'], how='any')
print('删除缺失值后:', data1_merge_data3.shape)
删除缺失值前:  (21709, 10)
删除缺失值后: (18285, 10)
# 展示数据
data1_merge_data3.head(3)
序号_x校园卡号性别专业名称门禁卡号序号_y进出时间进出地点是否通过描述
404118004118国际金融197486501346249.02019-04-02 09:46:00青鸾苑[出门]1.0允许通过
414118004118国际金融197486501346258.02019-04-02 10:31:00青鸾苑[进门]1.0允许通过
424118004118国际金融197486501346260.02019-04-02 00:00:00青鸾苑[出门]1.0允许通过
data1_merge_data3.to_csv('./task1_2_2.csv', index=False, encoding='utf-8-sig')

Part2 食堂就餐行为分析

任务2.1

绘制各食堂就餐人次的占比图,分析学生早中晚的就餐地点是否有差别,并在报告中进行描述。

data = pd.read_csv('./task1_2_1.csv')
data.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
0118000118国际金融19762330117331517.020181.02019-04-21 18:30:007.00.028.4206.0消费41.0249.0第四食堂
1118000118国际金融19762330117341866.020181.02019-04-22 09:40:003.50.024.9207.0消费19.0236.0第一食堂
2118000118国际金融19762330117154618.020181.02019-04-10 16:42:0011.00.02.7189.0消费82.018.0第四食堂
# 导入绘图库
#设置字体
from pylab import mpl
import matplotlib.pyplot as plt
mpl.rcParams["font.sans-serif"] = ["SimHei"]  # 显示中文
plt.rcParams['axes.unicode_minus'] = False		# 显示负号
# 忽略警告
import warnings
warnings.filterwarnings('ignore')
# 将食堂数据按食堂分类,并汇总数据量
canteen1 = data['消费地点'].apply(str).str.contains('第一食堂').sum()
canteen2 = data['消费地点'].apply(str).str.contains('第二食堂').sum()
canteen3 = data['消费地点'].apply(str).str.contains('第三食堂').sum()
canteen4 = data['消费地点'].apply(str).str.contains('第四食堂').sum()
canteen5 = data['消费地点'].apply(str).str.contains('第五食堂').sum()

apply:转换类型
contains:字符串匹配

# 绘制图形
cantee_names = ['食堂1', '食堂2', '食堂3', '食堂4', '食堂5']
man_count = [canteen1, canteen2, canteen3, canteen4, canteen5]
# 插件画布
plt.figure(figsize=(10, 6))
# 绘制饼图
plt.pie(man_count, labels=cantee_names, autopct='%1.2f%%')
# 显示比例
plt.legend()
# 添加标题
plt.title('食堂就餐人数占比图')
# 保持图像
plt.axis('equal')
# 显示图像
plt.show()


在这里插入图片描述

任务2.2

通过食堂刷卡记录,分别绘制工作日和非工作日食堂就餐时间曲线图,分析食堂早中晚的就餐峰值,并在报告中进行描述。

data.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
0118000118国际金融19762330117331517.020181.02019-04-21 18:30:007.00.028.4206.0消费41.0249.0第四食堂
1118000118国际金融19762330117341866.020181.02019-04-22 09:40:003.50.024.9207.0消费19.0236.0第一食堂
2118000118国际金融19762330117154618.020181.02019-04-10 16:42:0011.00.02.7189.0消费82.018.0第四食堂
# 观察数据类型
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 241079 entries, 0 to 241078
Data columns (total 16 columns):#   Column  Non-Null Count   Dtype  
---  ------  --------------   -----  0   序号      241079 non-null  int64  1   校园卡号    241079 non-null  int64  2   性别      241079 non-null  object 3   专业名称    241079 non-null  object 4   门禁卡号    241079 non-null  int64  5   流水号     241079 non-null  float646   校园卡编号   241079 non-null  float647   消费时间    241079 non-null  object 8   消费金额    241079 non-null  float649   存储金额    241079 non-null  float6410  余额      241079 non-null  float6411  消费次数    241079 non-null  float6412  消费类型    241079 non-null  object 13  消费项目编码  241079 non-null  float6414  操作编码    241079 non-null  float6415  消费地点    241079 non-null  object 
dtypes: float64(8), int64(3), object(5)
memory usage: 29.4+ MB
# 日期时间转换
data['消费时间'] = pd.to_datetime(data['消费时间'], format='%Y-%m-%d %H:%M:%S')
data.dtypes
序号                 int64
校园卡号               int64
性别                object
专业名称              object
门禁卡号               int64
流水号              float64
校园卡编号            float64
消费时间      datetime64[ns]
消费金额             float64
存储金额             float64
余额               float64
消费次数             float64
消费类型              object
消费项目编码           float64
操作编码             float64
消费地点              object
dtype: object
# 消费日和非消费日,故创建一个消费星期列
data['消费星期'] = data['消费时间'].dt.dayofweek + 1
data.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点消费星期
0118000118国际金融19762330117331517.020181.02019-04-21 18:30:007.00.028.4206.0消费41.0249.0第四食堂7
1118000118国际金融19762330117341866.020181.02019-04-22 09:40:003.50.024.9207.0消费19.0236.0第一食堂1
2118000118国际金融19762330117154618.020181.02019-04-10 16:42:0011.00.02.7189.0消费82.018.0第四食堂3
# 周一到周五工作日,其他为非工作日,拆分数据
# 创建 bool 索引
work_day_query = data.loc[:, '消费星期'] <= 5
unwork_day_query = data.loc[:, '消费星期'] > 5
# 获取数据
work_day_data = data.loc[work_day_query, :]
unwork_day_data = data.loc[unwork_day_query, :]
work_day_data.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点消费星期
1118000118国际金融19762330117341866.020181.02019-04-22 09:40:003.50.024.9207.0消费19.0236.0第一食堂1
2118000118国际金融19762330117154618.020181.02019-04-10 16:42:0011.00.02.7189.0消费82.018.0第四食堂3
3118000118国际金融19762330117200032.020181.02019-04-15 11:43:007.00.043.2192.0消费62.02.0第四食堂1
# 计算消费工作日对于时间消费的总次数
work_day_times = work_day_data['消费时间'].dt.hour.value_counts().sort_index()
work_day_times = work_day_times.tolist()
# 时间为x,同一时间段出现的次数为y
x = []
for i in range(24):x.append('{:02d}:00'.format(i))# 绘图
plt.plot(x, work_day_times, label='工作日')
plt.xlabel('时间')
plt.ylabel('次数')
plt.xticks(rotation=60)
plt.legend()
plt.grid()
plt.show()


在这里插入图片描述

unwork_day_times = []
for i in range(24):hour_str = f"{i:02d}"count = unwork_day_data['消费时间'].apply(lambda x : x.strftime('%H')).str.contains(hour_str).sum()unwork_day_times.append(count if count > 0 else 0)
# 绘图
plt.plot(x, unwork_day_times, label='非工作日')
plt.xlabel('时间')
plt.ylabel('次数')
plt.xticks(rotation=60)
plt.legend()
plt.grid()
plt.show()


在这里插入图片描述

Part3 学生消费行为分析

任务3.1

根据学生的整体校园消费数据,计算本月人均刷卡频次和人均消费额,并选择3个专业,分析不同专业之间不同性别学生群体的消费特点。

任务分析:

  • 任务:计算本月人均刷卡频次、人均消费额、分析不同专业不同性别学生消费特点;
  • 要求:选择不同三个专业。
data = pd.read_csv('./task1_2_1.csv')
data.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
0118000118国际金融19762330117331517.020181.02019-04-21 18:30:007.00.028.4206.0消费41.0249.0第四食堂
1118000118国际金融19762330117341866.020181.02019-04-22 09:40:003.50.024.9207.0消费19.0236.0第一食堂
2118000118国际金融19762330117154618.020181.02019-04-10 16:42:0011.00.02.7189.0消费82.018.0第四食堂
# 计算人均刷卡频次(总刷卡数量/学生人数)
cost_count = data['消费时间'].count()
student_count = data['校园卡号'].value_counts(dropna=False).count()
average_cost_count = int(round(cost_count / student_count))
print("人均刷卡频次: ", average_cost_count)
人均刷卡频次:  74
# 计算人均消费金额(总消费金额/学生人数)
cost_sum = data['消费金额'].sum()
average_cost_money = int(round(cost_sum / student_count))
print("人均消费额度: ", average_cost_money)
人均消费额度:  285
# 统计不同专业人数
data['专业名称'].value_counts()
专业名称
18连锁经营        12100
18机械制造        11181
18会计          10055
18宝玉石鉴定        8602
18金融管理         8494
18国际商务         8339
18模具设计         8331
18国贸实务         8201
18软件技术         8166
18商务英语         7452
18工程造价         7131
18旅游管理         6873
18皮具艺术         6792
18电子商务         6754
18审计           6564
18工业机器人        6463
18工业设计         6300
18建筑工程         6279
18电气自动化        6171
18建筑设计         6140
18计算机网络        6110
18工商企管         5763
18投资与理财        5544
18社会工作         5510
18汽车检测         5093
18市场营销         5092
18计算机应用        4546
18国际金融         4351
18艺术设计         4278
18嵌入式技术        4196
18商务日语         4154
18工业工程         3987
18酒店管理         3895
18物流管理         3666
18动漫设计         3520
18首饰设计         3411
18视觉传播         2941
18环境艺术         2853
18产品艺术         2550
18市政工程         1840
18机械制造(学徒)     1391
Name: count, dtype: int64

排名前三的是:18连锁经营、18机械制造、18会计
注意: 18机械制造是学徒,不算

# 选取消费最多的三个专业
subject1 = data['专业名称'].apply(str).str.contains('18连锁经营')
subject2 = data['专业名称'].apply(str).str.contains('18机械制造')
subject3 = data['专业名称'].apply(str).str.contains('18会计')
subject4 = data['专业名称'].apply(str).str.contains('18机械制造(学徒)')# 去除学徒的,这一步也是数据聚合
data_new = data[(subject1 | subject2 | subject3) ^ subject4]
data_new['专业名称'].value_counts()
专业名称
18连锁经营    12100
18机械制造    11181
18会计      10055
Name: count, dtype: int64
# 分别选取男生、女生数据
data_male = data_new[data_new['性别'] == '男']
data_female = data_new[data_new['性别'] == '女']
data_male.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
36987418007418会计19832682117305353.0201874.02019-04-21 16:10:000.0100.0115.9734.0存款202.0143.0财务处
36997418007418会计19832682117330658.0201874.02019-04-22 09:37:002.60.0106.2737.0消费114.08.0第五食堂
37007418007418会计19832682117330659.0201874.02019-04-22 09:38:002.10.0104.1738.0消费114.08.0第五食堂
data_female.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
41348118008118会计18929482117308277.0201881.02019-04-21 14:03:002.00.023.3616.0消费196.0133.0好利来食品店
41358118008118会计18929482117308744.0201881.02019-04-22 09:32:002.00.017.9619.0消费196.0133.0好利来食品店
41368118008118会计18929482117320320.0201881.02019-04-21 16:41:003.00.019.9618.0消费111.0204.0第五食堂

消费特点分析:

  • 特征选择:性别、总消费额、消费地点、总消费次数、消费时间
# 这一步:特征提取,计算不同学生的消费总额、消费次数
# 统计性别,并且从新设计索引
data_1 = data[['校园卡号', '性别']].drop_duplicates().reset_index(drop=True)
# 性别进行编码
data_1['性别'] = data['性别'].astype(str).replace(({'男': 1, '女': 0}))
# 按照校园卡号设置索引
data_1.set_index(['校园卡号'], inplace=True)
# 统计消费金额
# 只提取消费金额那一列
data_2 = data.groupby('校园卡号').sum()[['消费金额']]
data_2.columns = ['消费金额']  # 设置标题
# 统计消费次数
data_3 = data.groupby('校园卡号').count()[['消费时间']]
data_3.columns = ['总消费次数']
data_3
总消费次数
校园卡号
18000135
18000247
180004100
18000536
18000623
......
1843354
18433651
18433773
18433857
18433986

3268 rows × 1 columns

# 数据聚合
data_123 = pd.concat([data_1,data_2,data_3], axis=1)
data_123.head(3)
性别消费金额总消费次数
校园卡号
1800011161.635
1800021126.847
1800041572.0100

分析:采用聚类算法

from sklearn.cluster import KMeans  # 导入K-Meansk = 3  # 分成三类:高、中、低消费
iteration = 500   # 单次最大迭代数
# 数据标准化
data_zs = 1.0 * (data_123 - data_123.mean()) / data_123.std()# 创建聚类模型
model = KMeans(n_clusters=k, max_iter=iteration, random_state=123)# 聚类
model.fit(data_zs)
# 统计各类别的数目,
r1 = pd.Series(model.labels_).value_counts()  # 返回每一个聚类数量
# 聚类中心
r2 = pd.DataFrame(model.cluster_centers_)  # 返回每一个类别值
r = pd.concat([r2, r1], axis=1)
r.columns = list(data_123.columns) + ['类别数目']
# 将聚类类别加入data_123
r = pd.concat([data_123, pd.Series(model.labels_, index=data_123.index)], axis=1)
r.columns = list(data_123.columns) + ['聚类类别']
r.tail()
性别消费金额总消费次数聚类类别
校园卡号
184335041.042
1843360200.6512
1843370377.5730
1843380296.7572
1843390223.5862

任务3.3

通过对低消费学生群体的行为进行分析,探讨是否存在某些特征,能为学校助学金评定提供参考

# 统计消费金额最低500名的学生信息
# 统计
data_500 = data.groupby('校园卡号').sum()[['消费金额']]
# 排序
data_500.sort_values(by=['消费金额'], ascending=True, inplace=True)
# 选取
data_500 = data_500.head(500)
# 选取索引值
data_500_index = data_500.index.values  # values:转化成array
# 过滤
data_500 = data[data['校园卡号'].isin(data_500_index)]
data_500.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点
35218000218国际金融20521594117309755.020182.02019-04-22 12:01:000.0100.0103.5261.0存款202.0143.0财务处
36218000218国际金融20521594117394486.020182.02019-04-23 07:55:002.00.0101.5262.0消费105.0236.0第一食堂
37218000218国际金融20521594117394487.020182.02019-04-23 07:56:002.00.099.5263.0消费105.0236.0第一食堂
# 取出最低消费的500人,统计其最常去的消费地点
data_500['最常去的消费地点'] = data_500.groupby('校园卡号')['消费地点'].transform(lambda x : x.mode().iloc[0])
data_500.head(3)
序号校园卡号性别专业名称门禁卡号流水号校园卡编号消费时间消费金额存储金额余额消费次数消费类型消费项目编码操作编码消费地点最常去的消费地点
35218000218国际金融20521594117309755.020182.02019-04-22 12:01:000.0100.0103.5261.0存款202.0143.0财务处第一食堂
36218000218国际金融20521594117394486.020182.02019-04-23 07:55:002.00.0101.5262.0消费105.0236.0第一食堂第一食堂
37218000218国际金融20521594117394487.020182.02019-04-23 07:56:002.00.099.5263.0消费105.0236.0第一食堂第一食堂
# 统计去的各个食堂数目
data_max_place = data_500['最常去的消费地点'].value_counts(dropna=False)
data_max_place
最常去的消费地点
第二食堂      3225
第五食堂      2792
第三食堂      1075
第一食堂      1019
好利来食品店     538
第四食堂       536
红太阳超市       24
财务部         22
水电缴费处       10
教师食堂         7
第七教学楼        4
医务室          1
第一图书馆        1
Name: count, dtype: int64
# 画图显示
canteen_name = list(data_max_place.index)
man_count = list(data_max_place.values)
# 创建画布
plt.figure(figsize=(20, 10))
plt.pie(man_count, labels=canteen_name, autopct='%1.2f%%')
plt.legend()
# 添加标题
plt.title('最低消费学生常去地方')
plt.show()


在这里插入图片描述

# 统计余额最大值和最小值
data_500['余额'].min()  
0.0
data_500['余额'].max() 
326.4
data_500['消费金额'].min()
0.0
data_500['消费金额'].max()
128.25
data['消费金额'].max()
300.0

http://www.mrgr.cn/news/59821.html

相关文章:

  • 模拟退火算法
  • 数据结构与算法汇总整理篇——数组与字符串双指针与滑动窗口的联系学习及框架思考
  • 【文献及模型、制图分享】中国自然保护地典型治理模式成效比较——基于社区居民感知视角
  • IDEA如何快速复制日志生成sql语句,太妙啦
  • 逻辑推理学习笔记
  • 【Android】ViewPager的MVP架构搭建
  • 嵌入式——STM32外设应用
  • stm32的boot引脚接线
  • 《CUDA编程》10.线程束的基本函数与协作组
  • C++和Java该如何进行选择?
  • C++中获取硬盘ID的方法
  • 鸿蒙文本组件高级特性——富文本属性字符串
  • Python记录-字典
  • 设计模式(二)
  • ROM修改进阶教程------简单通过指令来修改系统安全设置中选项的的开启或者关闭 内置指令在rom中的应用
  • 从零实现数据结构:一文搞定所有排序!(下集)
  • 网络文件系统nfs实验1
  • 基于neo4j关系图谱的协同过滤科研推荐系统
  • 工具方法 - Omnifocus: 网页版基本操作
  • 软考:软件建模的抽象级别