Python数据分析之共享单车及建模探索(CLV建模、可视化)
开发环境
4.3【开发平台及环境】
Windons 10 教育版
Python 3.7
IntelliJ IDEA 2018.2.1 / PyCharm
Googe Chrome
数据清洗 分析模块pandas,numpy
可视化模块matplotlib
上期原创:
Python数据分析之智联招聘职位分析完整项目(数据爬取,数据分析,数据可视化)
链接: https://blog.csdn.net/weixin_46205203/article/details/104187696
一:数据格式
中文字段:
订单ID,用户ID,单车类型,开始时间,开始定位,结束定位
。
注释:后续会通过geohash模块计算经纬度转换成具体距离
数据大小:
180M
前言
数据涵盖了48万 + 的单车,涵盖了近35W的骑,通过导入Geohash脚本中的decode函数,获取经纬度,用haversine公式计算球面两点间的距离。并计算和预估每个用户的消费和统计单车骑行公里数超过多少提示报修
代码 控制台输出显示所有行from DPM_File.showed import showimport datetime# show()import pandas as pdimport geohashimport seaborn as snsfrom math import radians, cos, sin, asin, sqrtimport matplotlib.pyplot as pltfile = ‘F:/数据集/国内摩拜共享单车数据集/train.csv’df = pd.read_csv(‘%s’ % file, vps云服务器 sep=’,’, parse_dates=[‘starttime’])# 数据涵盖了48万 + 的单车,涵盖了近35W的骑bikeid_size, userid_size = df[‘bikeid’].unique().size, df.userid.unique().sizeprint(bikeid_size, ‘辆单车 ‘, userid_size, ‘用户’)# 抽取1%的数据df = df.sample(frac=0.002)print(‘抽取20%的数据:’, len(df))# 通过导入Geohash脚本中的decode函数,获取经纬度df[“start_lat_lng”] = df[“geohashed_start_loc”].apply(lambda s: geohash.decode(s))df[“end_lat_lng”] = df[“geohashed_end_loc”].apply(lambda s: geohash.decode(s))# # 获取出发地点所在区块周围的8个相邻区块编码# df[‘start_neighbors’] = df[‘geohashed_start_loc’].apply(lambda s: mzgeohash.neighbors(s))# # 提取区块对应的6位Geohash编码# df[“geohashed_start_loc_6”] = df[“geohashed_start_loc”].apply(lambda s: s[0:6])# df[“geohashed_end_loc_6”] = df[“geohashed_end_loc”].apply(lambda s: s[0:6])# # 获取出发地点所在区块周围的8个相邻区块的6位Geohash编码# df[“start_neighbors_6”] = df[“geohashed_start_loc_6”].apply(lambda s: mzgeohash.neighbors(s))# print(df.head(5))print(“Geohash编码处理完毕!”)# 判断目的地是否在当前区块或相邻区块内print(‘一阶完成!!!’)# 用haversine公式计算球面两点间的距离def haversine(lon1, lat1, lon2, lat2): # 这里error,需要专float类型才能进行运算 lon1, lat1, lon2, lat2 = map(radians, [float(lon1), float(lat1), float(lon2), float(lat2)]) dlon = lon2 – lon1 dlat = lat2 – lat1 # print(type(lon1.head(1))) # print(type(lon2.head(1))) # print(type(lat1.head(1))) # print(type(lat2.head(1))) a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2 c = 2 * asin(sqrt(a)) r = 6371 # 地球平均半径,单位为公里 return c * r * 1000df[“start_end_distance”] = df.apply(lambda s: haversine(s[‘start_lat_lng’][1],s[‘start_lat_lng’][0], s[‘end_lat_lng’][1],s[‘end_lat_lng’][0]), axis=1)print(‘二阶完成’)#获取小时df[‘hour’] = df[‘starttime’].apply(lambda s : s.hour)# print(df.head(5))hour_group = df[[‘userid’,’hour’]].groupby(‘hour’,as_index=False).count()print(hour_group.sort_values(‘userid’,ascending=False))hour_num_df = hour_group.agg({‘userid’:’count’}).reset_index()sns.barplot(x=hour_group[‘hour’],y = hour_group[‘userid’],data = hour_num_df)# plt.bar(hour_group[‘hour’],hour_group[‘userid’])sns.displot(df[‘start_end_distance’])plt.show()#单车报修统计’统计单车骑行公里数超过多少提示报修’number_bike = df[[‘bikeid’,’start_end_distance’]].groupby(‘bikeid’,as_index=False).sum()number_bike = number_bike[number_bike[‘start_end_distance’]> ]number_bike = number_bike.sort_values(‘start_end_distance’,ascending=False)print(number_bike.head(5))
结果 1
” start_end_distance ” 开始到结束的距离(单位:公里)
注释:180M数据,随机抽取了 20%
结果 2
每个时间段订单走势(赶时间省略100字)
注释:180M数据,随机抽取了 20%
结果 3
预估单车骑行公里数超过多少提示报修
number_bike = number_bike[number_bike[‘start_end_distance’]> N ]print(number_bike.head(5)) bikeid start_end_distance = N 有自行车行业经验的自行决定
439670 10754.385365
441905 9453.600628
251484 8895.594132
355054 8895.594132
385307 7830.297728
CLV探索
计算用户骑行距离所消费的金额money
‘3km=1元=5分钟’
‘6km=2元=10分钟’
‘12km=3元=15分钟’
‘经过上述统计得到2017-05-24 19:00:16为结束时间,数据量320W条’
‘统计frequency频次为0的占比(2017-05-10 到 2017-05-24之间)’
‘使用BG / NBD 模型分析频次和/新近度bgf’
‘预测前5大客户未来T=15天可能发生的购买频次’
‘未来T日可能产生多少ORI ?’
注释:这个个人定义的,实际骑行距离所用的时间因人而异
from lifetimes.utils import *from lifetimes import *from commerce.CLV.摩拜bike import dfimport pandas as pdimport datetime’1.分析用户未来5天可能消费的频次和消费金额(CLV建模)’# 需要的字段data = df[[‘userid’, ‘starttime’, ‘start_end_distance’]]# 筛选出骑行距离大于0的data = data[data[‘start_end_distance’] > 0]# 计算用户骑行距离所消费的金额money# ‘3km=1元=5分钟’# ‘6km=2元=10分钟’# ’12km=3元=15分钟’def fun(x): if 0 <= x < 3000: return 1 elif 3000 <= x < 5000: return 2 elif 5000 <= x < 7000: return 3 elif 7000 <= x < 9000: return 4 elif 9000 <= x < 11000: return 5 elif x >= 11000: return 50data[‘money’] = data[‘start_end_distance’].apply(lambda x: fun(x))# 特殊时间格式处理data[‘starttime’] = pd.to_datetime(data[‘starttime’], unit=’s’).dt.strftime(‘%Y-%m-%d %H:%M:%S’)print(data.head(5))print(list(data[‘starttime’]))# 将时间排序 ,查看开始日期到结束日期 0.003=2017-05-10 00:02:45 2017-05-24 18:58:01# a = list(data[‘starttime’])# def get_list(date):# return datetime.datetime.strptime(date, “%Y-%m-%d %H:%M:%S”).timestamp()# list = sorted(a, key=lambda date: get_list(date))# print(list[1])’经过上述统计得到2017-05-24 19:00:16为结束时间,数据量320W条’# CLV建模CLV_data = summary_data_from_transaction_data(data, ‘userid’, ‘starttime’, monetary_value_col=’money’, observation_period_end=’2017-05-24′)print(‘CLV建模后:’, len(CLV_data), ‘ 行\n’, CLV_data.head(5))# 统计frequency频次为0的占比(2017-05-10 到 2017-05-24之间)frequencys = (sum(CLV_data.frequency == 0) / len(data)) * 100print(‘频次为0的占比:’, round(frequencys, 2), ‘ %’, len(CLV_data), ‘ 行’)# 使用BG / NBD 模型分析频次和/新近度bgfbgf = BetaGeoFitter(penalizer_coef=0)bgf.fit(CLV_data[‘frequency’], CLV_data[‘recency’], CLV_data[‘T’])print(‘lifetimes数据: ‘, ‘\n’, bgf)print(‘lifetimes数据summary: ‘, ‘\n’, bgf.summary)# 预测前5大客户未来T=15天可能发生的购买频次T = 15data = CLV_data[CLV_data[‘frequency’] > 0]data[‘predicted_purchases’] = bgf.conditional_expected_number_of_purchases_up_to_time( T, data[‘frequency’], data[‘recency’], data[‘T’])# 未来T日可能产生多少ORI?data[‘ORI’] = data.monetary_value * data.predicted_purchasesROI = data.sort_values(by=’predicted_purchases’, ascending=False)# print(‘未来T日客户购买频次和ORI:’, len(data), ‘ 行\n’, data.head(5))print(‘预测15天内该前5大客户购买频次:’, ‘\n’, ROI.head(5))# 有时候出错,要检测 penalizer_coef (惩戒系数)
赶时间不写了(数据比较大,不上传了,要数据看主页加V)