您现在的位置是:首页 > 正文

《Python数据分析与挖掘实战》第12章——电子商务网站用户行为分析及服务推荐(协同推荐)数据探索分析篇①1 背景与目标分析2.数据探索分析

2024-02-01 02:55:11阅读 2

文章目录

  • 1 背景与目标分析

  • 2.数据探索分析

    • 2.1 网页类型分析

      • 2.1.1 统计各个网页类型所占的比例

      • 2.1.2 网页107类型中的内部统计

      • 2.1.3 统计带"?"问号网址类型统计

      • 2.1.4 统计199类型中的具体类型占比

      • 2.1.5 统计瞎逛用户中各个类型占比

    • 2.2 点击次数分析

      • 2.2.1 统计点击次数

      • 2.2.2 点击次数与用户数量关系

      • 2.2.3 统计1~7次数及7次以上的点击数

      • 2.2.4 浏览一次的用户行为分析

    • 2.3 网页排名

      • 2.3.1 网页点击率排名表

      • 2.3.2 获取网页点击排名数筛选出点击次数>50的有html结尾的网址

      • 2.3.3 翻页网页统计,对浏览网页翻页的情况进行统计

《Python数据分析与挖掘实战》的实战部分的第12章的数据——《电子商务网站用户行为分析及服务推荐》。

用一种方法解决问题,然后再结合别人的分析思路,优化自己的解决方案。(sql数据可能导入不全)

旨在补充原文中的细节代码,并给出文中涉及到的内容的完整代码。

在作者所给代码的基础上增加的内容包括:

1)原书中所分析的内容中缺少的代码

2)实现了协同过滤推荐结果展示;

3)实现了按照流行度推荐以及随机推荐;

1 背景与目标分析

  • 目标 分析某网站的用户访问记录,然后分析网页相关主题,分析用户网上访问行为;借助用户的访问记录,发现用户的访问习惯,对不同用户进行相关服务页面的推荐。

  • 实质:推荐算法。

2.数据探索分析

  • 读取数据

    import pandas as pd
    from sqlalchemy import create_engine
    
    engine = create_engine('mysql+pymysql://root:@localhost/wangye?charset=utf8')
    sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)
    '''
    用create_engine建立连接,连接地址的意思依次为“数据库格式(mysql)+程序名(pymysql)+账号密码@地址端口/数据库名(test)”,最后指定编码为utf8;
    all_gzdata是表名,engine是连接数据的引擎,chunksize指定每次读取1万条记录。这时候sql是一个容器,未真正读取数据。
    '''

2.1 网页类型分析

2.1.1 统计各个网页类型所占的比例

  • 统计fullURLId的数量

    counts = [ i['fullURLId'].value_counts() for i in sql] #按次10000存取,逐块统计
    
    counts = pd.concat(counts).groupby(level=0).sum() #合并统计结果,把相同的统计项合并(即按index分组并求和)
    counts = counts.reset_index() #重新设置index,将原来的index作为counts的一列。
    counts.columns = ['index', 'num'] #重新设置列名,主要是第二列,默认为0
    counts

在这里插入图片描述

  • 提取前3个数字做网页类别

    counts['type'] = counts['index'].str.extract('(\d{3})') #提取前三个数字作为类别id
    counts

0903125628634.png\)

  • 按类别合并

    counts_ = counts[['type', 'num']].groupby('type').sum() #按类别合并
    counts_.sort_values('num', ascending = False) #降序排列
    counts_['percentage'] = (counts_['num']/counts_['num'].sum())*100
    counts_.to_excel('./tmp/1_1_3type_counts.xlsx')
    counts_

在这里插入图片描述

  • 各网页类型中小类别占比

    # 每个大类别下面小类别占比
    a = counts.set_index(['type'])
    b = counts.groupby('type').sum()
    print(b)
    c = pd.merge(a,b,left_index=True,right_index=True)
    print(c)

在这里插入图片描述 添加网页类型百分比

    c['persentage'] = (c['num_x']/c['num_y'])*100
    del c['num_y']
    c.rename(columns={'num_x':'num'},inplace=True)
    c

在这里插入图片描述

2.1.2 网页107类型中的内部统计

  • 统计各类型的数量

    import pandas as pd
    from sqlalchemy import create_engine
    
    engine = create_engine('mysql+pymysql://root:@localhost/wangye?charset=utf8')
    sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)
    
    #统计107类别的情况
    def count107(i): #自定义统计函数
      j = i[['fullURL']][i['fullURLId'].str.contains('107')].copy() #找出类别包含107的网址
      j['type'] = None #添加空列
      j['type'][j['fullURL'].str.contains('info/.+?/')] = u'知识首页' #info以/结尾
      j['type'][j['fullURL'].str.contains('info/.+?/.+?')] = u'知识列表页'
      j['type'][j['fullURL'].str.contains('/\d+?_*\d+?\.html')] = u'知识内容页'
      return j['type'].value_counts()
    
    counts2 = [count107(i) for i in sql] #逐块统计
    counts2 = pd.concat(counts2).groupby(level=0).sum() #合并统计结果
    
    counts2.to_excel('./tmp/1_4type107.xlsx')
    print(counts2)

在这里插入图片描述

  • 百分比

    #计算各个部分的占比
    res107 = pd.DataFrame(counts2)
    # res107.reset_index(inplace=True)
    res107.index.name= u'107类型'
    res107.rename(columns={'type':'num'},inplace=True)
    res107[u'百分比'] = (res107['num']/res107['num'].sum())*100
    res107.reset_index(inplace = True)
    #保存的表名命名格式为“1_1_k+此表功能名称”,此表表示生成的第3张表格,功能为type107,计算知识类型各个小类型所占比例
    res107.to_excel('1_1_3type107.xlsx')
    res107

在这里插入图片描述

2.1.3 统计带"?"问号网址类型统计

2.1.4 统计199类型中的具体类型占比

2.1.5 统计瞎逛用户中各个类型占比

2.2 点击次数分析

目标:点击次数分析:统计分析原始数据用户浏览网页次数(以“真实IP”区分)的情况

2.2.1 统计点击次数

    import pandas as pd
    from sqlalchemy import create_engine
    
    engine = create_engine('mysql+pymysql://root:@localhost/wangye?charset=utf8')
    sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)
    
    #统计点击次数
    c = [i['realIP'].value_counts() for i in sql] #分块统计各个IP的出现次数
    count3 = pd.concat(c).groupby(level = 0).sum() #合并统计结果,level=0表示按index分组
    count_df = pd.DataFrame(count3) #Series转为DataFrame
    count3=count_df
    count3[1]=1 # 添加1列全为1
    print(count3.head())

在这里插入图片描述

2.2.2 点击次数与用户数量关系

    realIP_sum=count3['realIP'].sum()
    print(realIP_sum)
                                     
    count3= count3.groupby('realIP').sum()##统计各个“不同点击次数”分别出现的次数# 也可以使用counts1_['realIP'].value_counts()功能
    
    print(count3.head())
    
                                     
    count3.columns=[u'用户数']
    count3.index.name = u'点击次数'
    
    print(count3.head())

在这里插入图片描述

  • 用户点击次数所占百分比

    count3[u'用户百分比'] = count3[u'用户数']/count3[u'用户数'].sum()*100
    count3[u'点击记录百分比'] = count3[u'用户数']*count3.index/realIP_sum*100
    count3.sort_index(inplace = True)
    c=count3.iloc[:7,]
    c=c.T
    c

在这里插入图片描述

2.2.3 统计1~7次数及7次以上的点击数

    c.insert(0,u'总计',[count3[u'用户数'].sum(),100,100])
    c[u'7次以上'] = c.iloc[:,0]- c.iloc[:,1:].sum(1)
    
    c.to_excel('./tmp/2_2_2clickTimes.xlsx')
    c

在这里插入图片描述

  • 转置表格,并将所有输出保留两位小数

    d = c.T
    format = lambda x: '%.2f' % x  # 也可以使用d.round(4)
    d = d.applymap(format)
    d.T

在这里插入图片描述 从上表中可以看出大约80%的用户(不超过3次)只提供了大约30%的浏览量(几乎满足二八定律)。在数据中,点击次数最大值为23861次,对其进行分析,发现是律师的浏览信息(通过律师助手进行判断)。下表是对浏览次数达到7次以上的情况进行的分析,可以从中看出大部分用户浏览8到100次。

  • 分析浏览次数7次以上的用户

    # 分析浏览次数7次以上的数据
    times = counts1_.index[7:]
    bins = [7,100,1000,50000]
    cats = pd.cut(times,bins,right=True,labels=['8~100','101~1000','1000以上'])
    e = cats.value_counts()
    e = DataFrame(e, columns =[u'用户数'])
    e.index.name = u'点击次数'
     
    e[u'用户数'] = np.nan
    e.ix[u'8~100',u'用户数'] = a.loc[8:100,:][u'用户数'].sum()
    e.ix['101~1000',u'用户数'] = a.loc[101:1000,:][u'用户数'].sum()
    e.ix['1000以上',u'用户数'] = a.loc[1001:,:][u'用户数'].sum()
    e.sort_values(by=u'用户数',ascending=False,inplace = True)
    e.reset_index(inplace=True) 
    e

在这里插入图片描述

2.2.4 浏览一次的用户行为分析

    # 获取浏览一次的所有数据
    f = count_df[count_df['realIP']==1] # [i['realIP'].value_counts() for i in sql]
    del f[1]
    f.columns = [u'点击次数']
    f.index.name 

在这里插入图片描述

    import pandas as pd
    from sqlalchemy import create_engine
    
    engine = create_engine('mysql+pymysql://root:@localhost/wangye?charset=utf8')
    sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)
    # g = [pd.merge(f,i[['fullURLId','fullURL','realIP']],right_on = 'realIP',left_index=True,how ='left') for i in sql]
    g = [i[['fullURLId','fullURL','realIP']] for i in sql]
    g = pd.concat(g)
    h = pd.merge(f,g,right_on = 'realIP',left_index=True,how ='left')
    h.head()

在这里插入图片描述

  • 浏览一次的用户的网页类型ID分析

    # 浏览一次的用户的网页类型ID分析
    i = h['fullURLId'].value_counts()
    i = pd.DataFrame(i)
    print(i)
    i.rename(columns={'fullURLId':u'个数'},inplace=True)
    i.index.name = u'网页类型ID'
    i[u'百分比'] = i[u'个数']/i[u'个数'].sum()*100
     
    #保存的表名命名格式为“1_2_k此表功能名称”,此表表示生成的第2张表格,功能为typeID:浏览一次的用户的网页类型ID分析
    i.to_excel('./tmp/2_3_4typeID.xlsx')

在这里插入图片描述

  • 提取个数大一百的类型

    j=i[i[u'个数']>100]
    
    j.loc[u'其他',u'个数'] = i[i[u'个数']<=100][u'个数'].sum()
    j.loc[u'其他',u'百分比'] = i[i[u'个数']<100][u'百分比'].sum()
    j# 浏览一次的用户中浏览的网页类型ID

在这里插入图片描述 针对浏览次数为一次的用户进行分析,其结果如上图所示。其中,问题咨询页占比74%,知识页占比16%,而且这些记录基本上全是通过搜索引擎进人的。 由此可以猜测两种可能:

  1. 用户为流失用户,在问题咨询与知识页面上没有找到相关的需要。

  2. 用户找到其需要的信息,因此直接退出。综合这些情况,可以将这些点击一次的用户行为定义为网页的跳出率。为了降低网页的跳出率,需要对这些网页进行针对用户的个性化推荐,帮助用户发现其感兴趣或者需要的网页。

  • 用户点击1次所浏览网页统计(点击数大于100次的)

    # 点击1次用户浏览网页统计(点击数大于100次的)
    k = pd.DataFrame(h['fullURL'].value_counts())
    k.index.name = u'网址'
    k.columns = [u'点击数']
    m = k[k[u'点击数'] > 100]
    m.loc[u'其他',u'点击数'] = k[k[u'点击数']<=100][u'点击数'].sum()
    m[u'百分比'] = m[u'点击数']/k[u'点击数'].sum()
    #保存的表名命名格式为“1_2_k此表功能名称”,此表表示生成的第3张表格,功能为lookMorethan100:点击1次用户浏览网页统计(点击数大于100次的)
    m.to_excel('./tmp/2_3_5lookMorethan100.xlsx')
    m

在这里插入图片描述 结论:排名靠前的都是知识与咨询页面,因此可以猜测大量用户的关注都在知识或咨询页面上。

2.3 网页排名

2.3.1 网页点击率排名表

    import pandas as pd
    from sqlalchemy import create_engine
    
    engine = create_engine('mysql+pymysql://root:@localhost/wangye?charset=utf8')
    sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)
    # g = [pd.merge(f,i[['fullURLId','fullURL','realIP']],right_on = 'realIP',left_index=True,how ='left') for i in sql]
    
    def clickfreq(i): #自定义统计函数
        j = i[['fullURL','fullURLId','realIP']][i['fullURL'].str.contains('\.html')]
        return j
    
    counts1 = [clickfreq(i) for i in sql] #
    counts1 = pd.concat(counts1)
     
    counts1_ = counts1['fullURL'].value_counts()
    counts1_ = pd.DataFrame(counts1_)
    
    counts1_.columns = [u'点击次数']
    counts1_.index.name = u'网址'
    a = counts1_.sort_values(u'点击次数',ascending=False).iloc[:20,:]
    a

在这里插入图片描述

2.3.2 获取网页点击排名数筛选出点击次数>50的有html结尾的网址

    b = counts1_.reset_index()
    c = b[b[u'点击次数']>50][b[u'网址'].str.contains('/\d+?_*\d+?\.html')]
    c.set_index(u'网址',inplace=True)
    c.sort_index(inplace = True)
    # savetosql(c, 'count355')# 并保存到数据库中
    c

在这里插入图片描述

2.3.3 翻页网页统计,对浏览网页翻页的情况进行统计

  • 获取网址中以http://与.html中间的主体部分,即去掉翻页的内容

    # 获取网址中以http://与.html中间的主体部分,即去掉翻页的内容,即去掉尾部"_d"
    import re
    import numpy as np
    pattern = re.compile('http://(.*\d+?)_\w+_\w+\.html$|http://(.*\d+?)_\w+\.html$|http://(.*\w+?).html$',re.S)
    c['websitemain'] = np.nan
    for i in range(len(c)):
        items = re.findall(pattern, c.index[i])
        if len(items)== 0:
            temp = np.nan
        else:
            for j in items[0]:
                if j !='':
                    temp = j
        c.iloc[i,1] = temp
    c

在这里插入图片描述

  • 获取所有网页主体的网页数

    d = c['websitemain'].value_counts()
    d = pd.DataFrame(d)
    d

在这里插入图片描述

  • 统计网页主体出现次数为不少于二次的,即存在翻页的网址

    # 统计网页主体出现次数为不少于二次的,即存在翻页的网址
    e = d[d['websitemain']>=2]
    e.columns=['Times']#记录某网页及子网页出现的次数
    e.index.name='websitemain'# 主网页
     
    e['num'] = np.arange(1,len(e)+1) 
    f = pd.merge(c,e,left_on='websitemain',right_index=True,how='right')
    f.sort_index(inplace=True)
    f['per'] = np.nan
    f# 相同num的网页是拥有同一网页主体

在这里插入图片描述

  • 统计翻子页的点击率与上一页网页点击率的比重

    # 统计翻子页的点击率与上一页网页点击率的比重(注意:用此处这个方法对网页翻页后序号有10页及以上的合适
    def getper(x):
        x.sort_index(inplace=True) #必须先排序将网页
        x
        for i in range(len(x)-1):
            x.iloc[i+1,-1] = x.iloc[i+1,0]/x.iloc[i,0]
        return x    
            
    result = pd.DataFrame([]) # 用一个空表格记录值
    for i in range(1,f['num'].max()+1):#count36['num'].max()+1
        k= getper(f[f['num'] == i])
        result = pd.concat([result,k])# 每次进行一次操作时
    f['Times'].value_counts() # 由统计结果看,只有一个主网址出现过10次及以上,该数据采用上述方法会出问题,因此,在结果中将其剔除后观察剩余数据

在这里插入图片描述

    flipPageResult = result[result['Times']<10]
    #保存的表名命名格式为“1_3_k此表功能名称”,是此小节生成的第1张表格,功能为flipPageResult:统计翻子页的点击率与上一页网页点击率的比重
    flipPageResult.to_excel('./tmp/3_flipPageResult.xlsx')
    flipPageResult

在这里插入图片描述

网站文章

  • centos7下使用docker安装gitlab【转】

    centos7下使用docker安装gitlab【转】

    环境背景:Docker化已经成为一种热门,记录一下使用docker引擎安装gitlab的过程。测试环境:系统软件依赖CentOS 7.4GitLab(latest)docker-ce 18安装过程:1. 安装docker引擎并启动[root@server-10 ~]# yum instal...

    2024-02-01 02:55:02
  • select count(t.id)时遇到java.lang.ClassCastException: java.lang.Long

    重用以前的分页程序setTotalCount(sql)失败,遇到java.lang.ClassCastException: java.lang.Long异常 解决办法:将((Integer) result.get(0)).intValue();改为:((Long) result.get(0)).intValue(); 显然是sql统计语句返回类型改变了,类似问题可以

    2024-02-01 02:54:35
  • Vant-UI库和Element-UI库修改样式无效

    Vant-UI库和Element-UI库修改样式无效 最近用vue写页面时,发现使用vant的有些UI组件,而又不能满足自己的样式,修改CSS样式还是无效。css一般都会使用sass或者less,加了...

    2024-02-01 02:54:29
  • 通过实现AutoCloseable接口实现资源连接的关闭

    通过实现AutoCloseable接口实现资源连接的关闭

    自动关闭资源连接的好处在Java开发过程中,按照正常的设计开发的结构来讲,大部分程序应该是面向接口的开发,应该在接口里面提供所有的核心业务的功能,但是像及时释放连接资源的操作属于非核心业务功能。每次手...

    2024-02-01 02:54:22
  • idea marketplace plugins are not loaded 解决方案

    File—>Setting—>Appearance&Behavior—>System Settings—>HTTP Proxy进行配置,https://plugins.jetbrains.com/

    2024-02-01 02:54:15
  • SecurityContextHolder.getContext().getAuthentication()为null解决方案

    SecurityContextHolder.getContext().getAuthentication();为null解决方案 SpringSecurity。之前想用SecurityContextH...

    2024-02-01 02:53:45
  • 大厂面经系列 | 前端 | 美团,字节,京东,顺丰,携程 等题目分享

    一、HTML+CSS 实现左侧固定宽度,右侧自适应的布局,有几种方式?如果用display:inline-block可以实现么?有什么问题? 实现一段文本垂直上下居中有几种方式? 假如设计稿的文字有6...

    2024-02-01 02:53:38
  • Nexus私服搭建及Maven集成(Windows版本 - 巨详细)

    Nexus私服搭建及Maven集成(Windows版本 - 巨详细)

    一、Nexus下载 下载地址:https://www.sonatype.com/products/repository-oss-download PS:此处链接访问后,会让你填一些信息才能让你访问到具...

    2024-02-01 02:53:30
  • 叠纸测试开发一面 凉经(投测试 因为 一志愿 软开被挂了)

    I 小白的代数题题目大意小曾的手上最开始有 个糖果,现在有 次操作,每次操作能将小曾手上的数变为原来的 倍加上 个,求每次操作后小曾手上的糖果数之和。等到今天才告诉我offer审批没有通过,我...

    2024-02-01 02:52:59
  • 使用Mybatis框架

    使用Mybatis框架

    配置文件,Spring Boot项目在启动时会自动读取此文件中的配置信息,如果配置信息中的属性名是特定的,Spring Boot还会自动应用这些属性值。在Spring Boot项目中,在。

    2024-02-01 02:52:51