手把手教你:基于Django的用户画像可视化系统

系列文章




一、项目简介

1.1 内容简介

本文主要介绍如何使用python搭建一个:基于Django的用户画像可视化系统。

本项目分为2部分:

  • 1、RFM模型构建,用户画像数据输出。
  • 2、网站搭建,提供用户画像查阅功能。

1.2 电信运营商的三个典型数据集

1、通话数据
2、短信数据
3、手机上网数据

  • 基于这三个数据集,结合RFM模型,构建用户标签体系
  • 给每个用户打上标签,对用户进行画像
  • 画像后的数据可以用于推荐、精准营销、客群分析等

博主也参考过机器学习模型的文章,但大多是理论大于方法。很多同学肯定对原理不需要过多了解,只需要搭建出一个可视化系统即可。

也正是因为我发现网上大多的帖子只是针对原理进行介绍,功能实现的相对很少。

如果您有以上想法,那就找对地方了!


不多废话,直接进入正题!

二、可视化展示界面

本项目最终展示界面是基于Django构建的网站,下面就介绍一下画像展示界面。

1.搜索界面

  • 本项目需要对应的用户手机号搜索对应的移动用户画像,在搜索过程中也进行了校验如输入的文本格式不符合手机号,将直接提示错误。
    搜索界面
  • 输入错误提示:
    输入错误提示

2.用户画像展示界面

  • 输入了正确手机号后,会根据搜索用户展示用户的画像

  • 用户:19900000383

用户画像1

  • 用户:19900035430
    用户画像2

三、背景介绍

以客户为中心目标是了解不同客户群体的需求,并向他们提供满足其个性化需求的服务——提供了更多附加值,与此同时也获得高于平均的客户价值。随着电信业产品同质化的趋势越来越明显,企业成功不能再单纯依靠创新产品和产品价格取胜。倾听客户呼声和需求、对不断变化的客户期望迅速作出反应的以客户为中心运营能力——已经成为当今企业能否成功的关键。

市场环境、运营重心和管控模式的转变,要求客户运营更具灵敏性、高效性,以客户洞察为核心的客户经营中心系统实现了“客户-产品”的双向自动匹配,支撑CRM、电子渠道等精准营销策略和客户需求信息的实时信息推送,培养了业务人员客户洞察能力。


四、模型构建思路

1.用户画像主流分析方法

1、历史趋势分析,分析对应客户数的历史变化情况
2、构成分析,按照品牌、地市、VIP等级等维度,分析对应客户数的构成情况
3、关联分析,分析主体与不同标签之间的关联程度
4、对比分析,分析主体与不同标签之间的对比情况

2.本项目分析方法

  • 本实验的第一个步骤:基于通话数据生成RFM模型数据,输出每个客户在每个标签上的RFM标签值,这是一个中间结果集,用于计算最终的标签。

R:最近一次通话时间与统计月末的距离天数
F:通话次数
M:通话时长

  • 最终数据结果示例如下:
手机号码标签R值F值M值
138*旅游100
138*美食010
138*健身110
131*旅游101
131*美食010
134*旅游011

五、代码介绍

  • 由于代码众多,博客中就不放入最终代码了,有需要的童鞋可以在【代码下载地址】下载所有代码。

1.数据介绍

  • 我们的数据分为2部分,大概思路就是通过找到移动号码拨打的各行业的固定电话,最终收敛形成移动号码画像。重要申明:因电话信息涉及用户个人敏感信息,本文所述所有数据均经过脱敏处理!

1.固定电话清单以及其行业分类:
固定电话清单以及其行业分类
2.移动电话用户,及其呼叫清单:
移动电话用户,及其呼叫清单

2.数据预处理

  • 需要将两种数据进行合并,合并成一个数据表后才能继续操作
data_tele = data_tele_tag.merge(data_tele_detail,left_on="desc_num",right_on='desc_num')
  • 处理完后数据情况:
    处理完后数据情况
  • 需要计算离月底最近的一次通话,所以需要进行日期的计算
data_tele["last_date"] = pd.to_datetime(data_tele.last_date,format='%Y-%m-%d')
data_tele["last_date_day"] = data_tele.last_date.dt.day
data_tele["diff_date"] = (31 - data_tele["last_date_day"]).astype('int')
  • 完成数据预处理后数据情况:
    在这里插入图片描述

3.电话数据RFM数据制作

  • 分别计算不同电话、不同标签的最近一次通话、通话总次数以及通话总时长
def make_rfm(x):
    def get_format_rfm(xx):
        temp_date = xx.nsmallest(1,'diff_date')['diff_date'].iloc[0]
        temp_count = xx['count'].sum()
        temp_duration = xx["duration"].sum()
        tem_series = pd.Series([temp_date,temp_count,temp_duration],index=['last_date','count','duration'])
        return tem_series
    return x.groupby('tag').apply(get_format_rfm)
data_tele_rfm = data_tele.groupby("tele_num").apply(make_rfm)
data_tele_rfm = data_tele_rfm.reset_index()
# 保存
data_tele_rfm.to_csv("data/tele数据rfm数据表.csv",encoding='utf-8-sig',index=False)

4.短信数据RFM数据制作

  • 具体制作流程和电话数据是一致的,只是需要加载不同的数据集
#不同sms不同电话标签的RFM值的提取
def make_rfm_sms(x):
    def get_format_rfm_sms(xx):
        temp_date = xx.nsmallest(1,'diff_date')['diff_date'].iloc[0]
        temp_count = xx['count'].sum()
        temp_duration = xx['count'].sum()
        tem_series = pd.Series([temp_date,temp_count,temp_duration],index=['last_date','count','duration'])
        return tem_series
    return x.groupby('tag').apply(get_format_rfm_sms)
data_sms_rfm = data_sms.groupby("tele_num").apply(make_rfm_sms)
data_sms_rfm = data_sms_rfm.reset_index()
# 保存
data_sms_rfm.to_csv("data/短信数据rfm数据表.csv",encoding='utf-8-sig',index=False)

5.APP数据RFM数据制作

  • 具体制作流程和电话数据是一致的,只是需要加载不同的数据集
#不同app不同标签,的RFM值的提取
def make_rfm_app(x):
    def get_format_rfm_app(xx):
        temp_date = xx.nsmallest(1,'diff_date')['diff_date'].iloc[0]
        temp_count = xx['count'].sum()
        temp_duration = xx['count'].sum()
        tem_series = pd.Series([temp_date,temp_count,temp_duration],index=['last_date','count','duration'])
        return tem_series
    return x.groupby('tag').apply(get_format_rfm_app)
data_app_rfm = data_app.groupby("tele_num").apply(make_rfm_app)
data_app_rfm = data_app_rfm.reset_index()
# 保存
data_app_rfm.to_csv("data/app数据rfm数据表.csv",encoding='utf-8-sig',index=False)
# 此次运行耗时较长,可以直接执行加载数据集的方法,此数据集是上述代码执行的结果

6.数据归一化,最终数据合并,生成标签

  • 最终要生成one-hot矩阵,进行标签确认的前提就是rfm值中超过两个存在,或者flag_duration这个值是1就贴上标签
#对合并后的表中每个用户在每个标签类别的RFM求和
data_numbers = data_total.groupby(["tele_num",'tag']).sum().reset_index()
#求和后大于0的标为1
columns_names = ['flag_days','flag_count','flag_duration']
for name in columns_names:
    data_numbers[name] = data_numbers[name].apply(lambda x: 1 if x>0 else 0)

#通过2个条件过滤无价值用户,只保留RFM中3个值的和为2以上的以及M值为1的有价值用户
data_numbers['condition1'] = data_numbers['flag_days']+data_numbers['flag_count']+data_numbers['flag_duration']
data_numbers['condition2'] = data_numbers['flag_duration'].apply(lambda x:1 if x==0 else 0)
data_result_pre = data_numbers[(data_numbers['condition1']>1) | (data_numbers['condition2']==1)]

#添加所有标签对应的列
tags = data_result_pre.tag.value_counts().index
for tag_ in tags:
    data_result_pre[tag_] = data_result_pre['tag'].apply(lambda x:1 if x==tag_ else 0)
#删除无用列
x=[2,3,4,5,6]
data_result_pre.drop(data_result_pre.columns[x], axis=1, inplace=True)
#合并每个用户的标签
data_numbers1 = data_result_pre.groupby(["tele_num"]).sum().reset_index()
data_numbers1.head(20)
  • 最终数据效果如前文所展示的:
    最终数据效果如前文所展示的

7.展示界面

  • 完成上述用户画像模型构建后就是页面展示,本项目采用了Django进行展示。
  • 用户验证与输入检测:
def get_ans(request):
    text = request.POST["input_text"]
    print("获取的号码:", text)
    if text is "":
        context = {
            "state": "1",
            "text": "输入的内容为空,请重新输入想要查询的号码!"
        }
        return render(request, 'error.html', context)
    else:
        if is_number(text):
            context = user_get(int(text))
            if context == {}:
                context = {
                    "state": "3",
                    "text": "查询的号码不存在,请输入正确的号码!"
                }
                return render(request, 'error.html', context)
            else:
                return render(request, 'user_class.html', context)
        else:
            context = {
                "state": "2",
                "text": "输入的内容包含其他字符,请输入正确的号码!"
            }
            return render(request, 'error.html', context)


# 输入检测
def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        pass
    try:
        import unicodedata
        unicodedata.numeric(s)
        return True
    except (TypeError, ValueError):
        pass
    return False

六、代码下载地址

由于项目代码量和数据集较大,感兴趣的同学可以直接下载代码,使用过程中如遇到任何问题可以在评论区进行评论,我都会一一解答。

代码下载:

  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大雾的小屋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值