读取数据
分隔符
read_csv(sep='s+')
转化为日期格式
pd.to_datetime(一列, format("%Y%m%d"))
日期只保留月份
只有ndarray、series都可以使用astype方法,所以需要values取得对应的array
df['dt‘].values.astype('datetime64[M]')
df['dt'].astype('datetime64[M]') 得到的结果相同
这样可以帮助我们按月汇总
月消费趋势分析
月消费总额求和
df.groupby('month').order_amount.sum()
对多个字段汇总计算
agg需要传入一个字典
df['am', 'user_id', 'pro_count'].agg({'am':'sum', user_id:count, pro_count:sum})
重置索引
reset_index 可以把索引month列变为一个普通的列
修改列名
修改列名,传入columns参数【是一个字典】
对一个列去重
df.user_id.unique()
对每一组去重
grouped_info :dfgroupedby类型
grouped_info[A]:dfseries类型 可以在上面施加 .unique() 方法
apply方法使用注意事项
凡是可以在对象上 .出来的函数,例如unique(),astype() 方法。都可以直接在矢量上面 .出来
凡是可以接受一个对象作为入参的函数,都可以通过apply施加到 矢量上面。例如:sum,len, str等方法
相对于apply来讲,map更加的轻量,一般用在字符串格式化等场合,施加函数的话 apply更适合
如果函数不想单独写的话,可以把lambda表达式传给 apply
-
有些函数既可以点出来,又可以把对象作为入参,这种情况下 矢量直接点和apply效果一样,如下例:
image-20200628105553828
pandas日期在powerBI中展示日期
grouped_info_agg['month'] = grouped_info_agg['month'].astype(str)
不然在powerBI中会变成时间戳,,字符串的话传入字后是年月日
数据透视表
相当于少写了一步groupby并且筛选列的 代码,但是个人还是喜欢一步一步来。
df.pivot_table(index=month,
values=[am, user_id, pro_count],
aggfunc={am:sum, user_id:count, pro_count:sum})
用户个体消费分析
消费金额和次数的关系
groupby('user_id').sum() 会自动帮我们求和 pro_count,order_amount 这种字段
describe分析
对sum() 直接describe可以看到每个用户的平均值等
趋势线拟合
金额和数量的关系
在分析 tab里面
对于干扰性的极值,我们可以用筛选器取出
分布情况
pd.cut
用到了列表生成区间: list = [i for i in range(0, max+50, 50)]
bins=list
或者 bins=100 直接写数量也可以,但是会出现小数,所以一般用列表
labels数组比bins数组长度少1
极值的筛选:切比雪夫不等式
95%的数据在5个标准差之内。
消费累计百分比
grouped_user_info.order_amount 这时候是seriesgroupby的类型
对其sum一下子就是series了。
排序
sort_values('列名')
对df施加apply
其实是对于每一列施加。
df.apply(lambda x:x.cumsum()/x.sum())
cumsum的展示注意
需要重置索引,保证索引是递增的,否则会跳动
中值线
会把自变量 从中间分
可以帮我们验证28法则。
在运营上我们应该抓大放小
用户消费行为
每个月份多少新增
user_first_dt = groupby('user_id').order_dt.min()
再groupby(order_dt)可以得到每个月有多少新用户
再value_counts可以得到每个月的用户数。
此时可以reset_index就会变成一个df,然后df.dt.astype(str)否则在powerBI中会变成时间戳。
每个月用户的流失
最后一天
新老用户的消费比
is_only_buy_one = grouped_user.dt.min==grouped_user.dt.max.
每月的新客占比
groupby(user_id).min():得到每个用户的第一天
groupby(user_id, month).min():得到该用户在本月的第一天
RFM模型
groupby(user_id), order_date->max, product_num->sum, order_amount->sum;
日期归一化
rfm.order_dt - rfm.order_dt.max / np.timedelta64(1, 'D')可以知道差距多少天
这个日期作为R,order_product->F, order_amount->M.
先算出来是否大于均值
rfm.apply(lambda x:x-x.mean())
根据正负关系打标签
传入x
x = x.apply(lambda x:'1' if x>0 else '0') #这是每个数值变成了字符类型
ret=x.R+x.F+x.M
就可以为ret定义一个字典
d={111:重要价值客户,
011:重要保持客户,
101:重要发展客户,
001:重要挽留用户,
110:一般价值客户,
010:一般保持客户,
100:一般发展客户,
000:一般挽留用户}
根据A列修改B列
rfm.loc[rfm.label=='重要价值客户', ’color‘]='重要价值客户’
rfm.loc[~(rfm.label='重要价值客户'), ’color‘]='重要价值客户’
还有里面取反的方式需要注意
用户生命周期
用户状态的定义
非用户---新--活跃
-- 不活跃--回流
--流失
user_id, month 的数据透视表
数据透视表
高端应用: index=user_id, columns=month, aggfunc={'order_dt':'count'}
这么用的时候会出现multiindex多重索引,如果只想要一重索引,应该用
values=order_dt, aggfunc=count
applymap
应该到每个元素
每个月状态的计算
def active_status(user):
ret = [];
for i in range(0, 18):
if (user[i]==0):
if (len(ret) == 0):
ret[i] = 'unreg';
else
if (ret[i-1]=='unreg'):
ret[i] = 'unreg'
else
ret[i] = 'unactive'
else:
if (len(ret) == 0):
ret[i] = 'new'
else:
if (ret[i-1]=='unreg'):
ret[i] = 'new'
else:
if (ret[i-1]=='unactive'):
ret[i] = 'return'
else:
ret[i] = 'active'
return ret;
用户关联月定位0,1 表示该月是否购买。
apply上面的状态函数,转为 unreg, new, active, unactive, return 五个子状态
unreg-->替换为np.nan
每一列value_counts就得到每个月有多少新用户,不活跃,活跃
NaN的使用
- 我们不希望统计未注册用户的数量,所以我们弄成NaN
- 当根据总数计算完毕 每种用户的比例,我们又需要作图0填充,就把NaN去掉
复购率的计算
可以通过函数实现 applymap(x: 1 if x>1 else 0 if x==0 else np.nan)
然后x.sum() / x.count() 得到复购率
回购率的计算
def cal_huigou:
t = x>0 # 表示是否购买
return t.shift & t # 表示连续都买了,才算作回购
df.apply(cal_huigou)
报告的路径如下:
https://zhuanlan.zhihu.com/p/151789421