目录
一、项目背景与目的
大数据具有信息量大、类型繁多、价值密度低、速度快、时效高的特点。随着互联网的发展,大数据在商业竞争中越来越显现出重要的作用,很多企业利用大数据进行储存、计算、分析并开展多层次的商业创新。在此背景下,消费者接触商品的方式发生了变化,购物呈现出多样化,消费理念和意识也随之发生了改变。当前在所有营销方式中,精准营销通过定量和定性相结合的方法,对目标市场的不同消费者进行细致分析,根据其消费心理和行为特征,采用现代技术、方法和指向明确的策略,实现对目标市场不同消费群体强有效性的营销沟通。基于这些优点,精准营销超越了传统的营销手段。
因此,本项目旨在通过对海量交易流水数据的深度分析与挖掘,构建全方位的客户标签体系。其次,基于客户标签体系,从基本信息、消费能力、行为习惯等多个维度对客户进行精准画像。最后,计算客户商品兴趣度排行榜,支持精准目标客户的筛选。通过此项目来进一步熟悉和掌握精准营销的方法与流程。
二、项目流程
#导入项目中所需的包
from io import StringIO
import pandas as pd
import re
import matplotlib.pyplot as plt
import matplotlib
import datetime
import seaborn as sns
import jieba
from wordcloud import WordCloud
import PIL
import numpy as np
from jieba import analyse
import copy
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
import matplotlib.dates as mdates
三、数据源
1. 数据介绍
本项目采用模拟的客户交易数据sell.sql进行分析,此数据包含40000条交易流水数据,每条交易记录包含客户id、交易金额、交易附言和交易时间四个字段,如下表所示。
字段名称 | 中文名称 | 备注 |
---|---|---|
user_id | 客户id | 客户唯一标识 |
payment | 交易金额 | 正为支出、负为收入 |
postscript | 交易附言 | 为此项交易的文字描述 |
unix_time | 交易时间 | unix时间戳 |
2. 数据解析与读取
直接利用pandas和re对sql数据进行解析和读取,最终转换为dataframe格式的数据。
代码参考:https://www.jb51.net/article/204513.htm
# 解析sql数据,将其转换为dataframe格式
# 首先将sql文件中的数据传换成str,利用正则表达式进行解析处理,用pandas读取,得到dataframe格式的数据
def read_sql_script_by_tablename(sql_file_path, table_name, quotechar="'") -> (str, dict):
# 参数说明
# sql_file_path表示sql文件读取路径
# table_name表示数据库表的名称
# quotechar表示用单引号解析还是用双引号解析,默认为单引号解析
insert_check = re.compile(r"insert +into +`?(\w+?)`?\(", re.I | re.A)
with open(sql_file_path, encoding="utf-8") as f:
sql_txt = f.read()
end_pos = -1
dfs = []
while True:
match_obj = insert_check.search(sql_txt, end_pos+1)
if not match_obj:
break
start_pos = match_obj.span()[1]+1
end_pos = sql_txt.find(";", start_pos)
if table_name != match_obj.group(1):
continue
tmp = re.sub(r"\)( values |,)\(", "\n", sql_txt[start_pos:end_pos])
tmp = re.sub(r"[`()]", "", tmp[53:])
df = pd.read_csv(StringIO(tmp),
quotechar=quotechar,
index_col = False,
header = None,
names = ['user_id','payment','postscript','unix_time'])
dfs.append(df)
return pd.concat(dfs)
四、数据预处理
1. 统计分析
(1)基本信息统计
可以看到交易附言字段中,数据由文本组成,后续需进行文本处理。交易金额字段有部分数据为NaN,后续需对其进行处理。交易时间字段的数据是unix时间戳,且数据的长度不一,unix时间戳一般情况下为10位数,后续需将其进行处理。由于该数据中无重复数据,故后续数据处理中不需要对其进行去重操作。
(2)客户信息及交易信息统计
# 计算客户个数
user_num = len(df['user_id'].unique())
print('客户总数为:',user_num)
# 计算客户交易次数
user_counts = df['user_id'].value_counts()
print('每个客户交易次数为:\n',user_counts)
可以看到在整个流水交易数据中,交易客户总数为301个,id为179的客户交易次数最多,而id为288的客户交易次数最少,此结果有助于后续的数据分析,从而实现对客户精准营销。
2. 异常值处理
unix_time字段数据长度不一,通过观察可以知道,有9位、10位和11位,需对其进行处理,我们知道unix时间戳一般为10位,故采用正则表达式来对数据进行匹配,检测位数不为10的数据对其进行处理。
# 书写正则表达式
pattern = '^[\d]{10}$'
# 筛选异常值
outlier = df[~df['unix_time'].astype(str).str.match(pattern)]
# 统计不同类型的异常值及其数量
outlier_counts = outlier['unix_time'].value_counts()
outlier_counts
可以看到有4947条数据都是异常数据,1000000000对应的北京时间为:,9999999999对应的北京时间为2286-11-21 01:46:39,为方便后续的数据分析与可视化,根据unix时间戳与北京时间的转换,设定具体的处理办法为:针对只有9位的数据在其所有数字前加1,针对11位的数据,将其最后一位删除。
for i in outlier['unix_time'].index: # 通过索引循环异常数据
s = str(outlier['unix_time'][i]) #将异常值赋值给s进行处理
if len(s)==9:
s = ''.join(['1', s]) # 处理unix时间戳为9位的异常值,在其数值第一位前加1
else:
s = s[:-1] # 处理unix时间戳为11位的异常值,删除其最后一位
df['unix_time'][i] = s # 处理完毕后,根据索引值代替原数据,异常值处理完毕
df
查看是否处理完成
可以看到unix_time字段的数据均成为10位,异常值处理完毕。
3. 缺失值处理
统计分析部分知道,payment字段中有NaN值,仅有45条,对本项目分析影响很小,故直接删除即可,删除后数据剩39955条。
4. 数据格式转换
(1)时间格式与时区转换
注:这里的时间数据稍微有点问题,但其实不妨碍分析。
由于unix_time字段的数据是unix时间戳格式,为便于后续分析,需将其转换为标准的时间格式,即“%Y-%m-%d %H:%M:%S”,并通过+8小时进行时区转换。
# 时间格式转换
df['pay_time'] = pd.to_datetime(df['unix_time'],unit='s',errors='coerce')
# 时区转换
df['pay_time'] = df['pay_time'] + pd.Timedelta(hours=8)
(2)交易金额数据格式转换
由于交易金额是以“分”为单位的,为了符合我们的习惯,将其转换为以“元”为单位。
# 交易金额数据格式转换(payment字段由以“分”为单位转换为以“元”为单位)
df['payment'] = df['payment']/100
五、客户交易行为分析
1. 时间维度分析
(1)交易次数随时间的可视化分析
# 交易次数随时间的可视化分析
fig = plt.figure(figsize=(12,6))
# 绘制折线图
df['pay_time'].dt.date.value_counts().plot()
# 设置图形标题
plt.title("不同时间的交易次数分布")
# 设置y轴标签
plt.ylabel("交易次数")
# 设置x轴标签
plt.xlabel("时间")
#设置中文显示
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['font.family']=['sans-serif']
plt.show()
由于jupyter不能将图局部放大,故使用spyder将图局部放大后,如下图,可以看到2026年9月到2029年5月期间,交易次数较频繁,故后续分析将着重针对此时间段内的数据进行分析。
注:由于数据的问题,后续所做的图只显示用spyder局部放大后的图。
(2)交易金额随时间的可视化分析
#交易金额随时间的可视化分析
fig = plt.figure(figsize=(12,6))
#绘制折线图
abs(df['payment']).groupby(df['pay_time'].dt.date).sum().plot() # 交易金额有正有负,代表资金流入流出。取绝对值代表交易金额有流动
#设置图形标题
plt.title("不同时间的交易金额分布")
#设置y轴标签
plt.ylabel("交易金额")
#设置x轴标签
plt.xlabel("时间")
#设置中文显示
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['font.family']=['sans-serif']
plt.show()
可以看到交易金额也集中在2026年9月到2029年5月这段时间,故后续分析将着重针对此时间段内的数据进行分析。
(3)交易有效时段设置
将时间限定再2026年9月1日到2029年5月31日之间,可以看到在这期间交易的数据由30576条。
# 时间限定
df = df[(df['pay_time']<=pd.Timestamp(2029,5,31)) & (df['pay_time']>=pd.Timestamp(2026,9,1))]
df.shape