学习《网站用户行为分析实验》总结

本文章学习的是厦门大学大数据课程的实验案例——网站用户行为分析,着重于Hadoop平台的操作,而不是数据的分析

软件版本与环境搭建

Linux系统:Ubuntu 14.04

Hadoop:2.7.7

MySQL:5.7.16

HBase:1.3.6
Hive:1.2.2
Sqoop:1.4.7
R:3.0.2
Eclipse:3.8

本地数据集上传到数据仓库Hive

数据下载

首先把数据集下载到Ubuntu的Download目录中,然后把数据集存放到专门的位置/usr/local/bigdatacase/dataset

    cd /usr/local
    ls
    sudo mkdir bigdatacase
    //这里会提示你输入当前用户(本教程是hadoop用户名)的密码
    //下面给hadoop用户赋予针对bigdatacase目录的各种操作权限
    sudo chown -R hadoop:hadoop ./bigdatacase
    cd bigdatacase
    //下面创建一个dataset目录,用于保存数据集
    mkdir dataset
    //下面就可以解压缩user.zip文件
    cd ~  //表示进入hadoop用户的目录
    cd 下载
    ls
    unzip user.zip -d /usr/local/bigdatacase/dataset
    cd /usr/local/bigdatacase/dataset
    ls

数据说明:

user_id(用户id)
item_id(商品id)
behaviour_type(包括浏览、收藏、加购物车、购买,对应取值分别是1、2、3、4)
user_geohash(用户地理位置哈希值,有些记录中没有这个字段值,所以后面我们会用脚本做数据预处理时把这个字段全部删除)
item_category(商品分类)
time(该记录产生时间)

数据处理

文件第一行记录是每个字段的名称,对我们的分析没有用,故删除文件第一行的记录

    cd /usr/local/bigdatacase/dataset
    //下面删除raw_user中的第1行
    sed -i '1d' raw_user //1d表示删除第1行,同理,3d表示删除第3行,nd表示删除第n行
    //下面删除small_user中的第1行
    sed -i '1d' small_user
    //下面再用head命令去查看文件的前5行记录,就看不到字段名称这一行了
    head -5 raw_user.csv
    head -5 small_user.csv

接着丢弃user_geohash字段,因为对我们的分析没有用。然后为每一行记录增加一个省份字段,用于后面的可视化分析。这里需要创建一个shell脚本来处理。

    cd /usr/local/bigdatacase/dataset
    vim pre_deal.sh

pre_deal.sh的内容:

    #!/bin/bash
    #下面设置输入文件,把用户执行pre_deal.sh命令时提供的第一个参数作为输入文件名称
    infile=$1
    #下面设置输出文件,把用户执行pre_deal.sh命令时提供的第二个参数作为输出文件名称
    outfile=$2
    #注意!!最后的$infile > $outfile必须跟在}’这两个字符的后面
    awk -F "," 'BEGIN{
            srand();
            id=0;
            Province[0]="山东";Province[1]="山西";Province[2]="河南";Province[3]="河北";Province[4]="陕西";Province[5]="内蒙古";Province[6]="上海市";
            Province[7]="北京市";Province[8]="重庆市";Province[9]="天津市";Province[10]="福建";Province[11]="广东";Province[12]="广西";Province[13]="云南"; 
            Province[14]="浙江";Province[15]="贵州";Province[16]="新疆";Province[17]="西藏";Province[18]="江西";Province[19]="湖南";Province[20]="湖北";
            Province[21]="黑龙江";Province[22]="吉林";Province[23]="辽宁"; Province[24]="江苏";Province[25]="甘肃";Province[26]="青海";Province[27]="四川";
            Province[28]="安徽"; Province[29]="宁夏";Province[30]="海南";Province[31]="香港";Province[32]="澳门";Province[33]="台湾";
        }
        {
            id=id+1;
            value=int(rand()*34);       
            print id"\t"$1"\t"$2"\t"$3"\t"$5"\t"substr($6,1,10)"\t"Province[value]
        }' $infile > $outfile

代码解释:
第一行注释#!/bin/bash#!是特殊的表示符,其后跟的是解释这个脚本的shell路径。有的是#!/bin/ba,两者没有太大不同,只是有一些不同标准。#!/bin/sh#!/bin/bash的缩减版。
上面代码的基本逻辑是:awk -F "," '处理逻辑' $infile>$outfileawk命令对输入的文本逐行读取。-F参数表示每一行记录的不同字段用什么分隔符,这里用的是逗号。
srand();用来生成随机数的种子,id用来为每一条数据添加一个唯一的身份值,rand函数用来生成一个随机数,value的值在0-33之间。substr($6,1,10)是为了截取时间字段的年月日,参数含义是:$6:表示第6个字段;1,10:表示截取前十个字符。第6个字段类似于“2014-12-08 12”,这样前十个字符就是年月日了。
put语句:用"\t"分割每一个字段,这里只选取第1、2、3、5、6字段

执行代码:

    cd /usr/local/bigdatacase/dataset
    bash ./pre_deal.sh small_user.csv user_table.txt

这里先处理这个小的数据文件small_user.csv,等到在小的文件上运行成功后再用大的文件row_user.csv

导入数据库

启动HDFS,上传数据文件

    cd /usr/local/hadoop
    ./sbin/start-all.sh
    ./bin/hdfs dfs -mkdir -p /bigdatacase/dataset
    ./bin/hdfs dfs -put /usr/local/bigdatacase/dataset/user_table.txt /bigdatacase/dataset
    ./bin/hdfs dfs -cat /bigdatacase/dataset/user_table.txt | head -10

代码逻辑:
HDFS中上传文件用-put,后面接源文件和HDFS上的目的路径

在Hive上创建数据库并导入

首先启动mysql服务,再启动Hive,然后创建表格并导入数据

    service mysql start
    cd /usr/local/hive
    ./bin/hive
    create database dblab;
    use dblab;
    #Hive中创建表格并从HDFS中导入数据的命令格式
    CREATE EXTERNAL TABLE dblab.bigdata_user(id INT,uid STRING,item_id STRING,behavior_type INT,item_category STRING,visit_date DATE,province STRING) COMMENT 'Welcome to xmu dblab!' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE LOCATION '/bigdataset/dataset';

代码解释:
这里创建的是外部表,用EXTERNAL参数表示,ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'指明文件的行分隔符,STORED AS TEXTFILE指明文件存储形式,LOCATION '/bigdatacase/dataset';指明文件在HDFS中的存储路径。

Hive数据分析

简单查询分析

    hive> use dblab;//切换数据库
    hive> show tables;//显示数据库中的所有吧表
    hive> show create table bigdata_user;//创建并查看表格的属性
    hive> desc bigdata_user;//查看表的结构
    
    //查看表中的内容
    hive> select * from bigdata_user limit 10;
    hive> select behavior_type from bigdata_user limit 10;
    //嵌套查询
    hive> select e.bh,e.it from (select behavior_type as bh,item_category as it from bigdata_user) as e limit 10;

查询条数统计分析

    hive> select count(*) from bigdata_user;
    //查询uid不重复的数据有多少条
    hive> select count(distinct uid) from bigdata_user;//distinct表示分离出每个不同的uid
    hive> select count(*) from (select uid,item_id,behavior_type,item_category,visit_date,province from bigdata_user group by uid,item_id,behavior_type,item_category,visit_date,province having count(*)=1)a;//a是嵌套语句的别名

关键字条件查询分析

    //查询2014-12-10到2014-12-13日有多少用户浏览了商品
    hive> select count(*) from bigdata_user where behavior_type='1' and visit_date>'2014-12-10' and visit_date<'2014-12-13';
    
    //以月的第n天为统计,显示第n天网站卖出去的商品个数
    hive> select count(distinct uid),day(visit_date) from bigdata_user where behavior_type='4' group by day(visit_date);
    
    //取给定时间和给定地点,求当天发出到该地点的货物的数量
    hive> select count(*) from bigdata_user where visit_date='2014-12-12' and province='江西' and behavior_type='4';

根据用户行为分析

    //查询一件商品在某天的购买比例或浏览比例
    hive> select count(*) from bigdata_user where visit_date='2014-12-12';
    hive> select count(*) from bigdata_user where visit_date='2014-12-12' and behavior_type='4';
    
    //查询某个用户在某一天点击网站占该天所有点击行为的比例(点击行为包括浏览,加入购物车,收藏,购买
    hive> select count(*) from bigdata_user where uid=xxxxxxxx and visit_date='2014-12-12';
    hive> select count(*) from bigdata_user where visit_date='2014-12-12';
    
    //给定购买商品的数量范围,查询某一天在该网站的购买该数量商品的用户id
    hive> select uid from bigdata_user where behavior_type='4' and visit_date='2014-12-12' group by uid having count(behavior_type='4')>5;
    

用户实时查询分析

    //某个地区的用户当天浏览网站的次数
    hive> create table scan(province STRING,scan INT) COMMENT 'This is the search of bigdataday' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE;
    
    hive> insert overwrite table scan select province,count(*) from bigdata_user where behavior_type='1' group by province;
    //或者下面的语句结果也一样
    hive> insert overwrite table scan select province,count(behavior_type) from bigdata_user where behavior_type='1' group by province;
    
    hive> select * from scan;

Hive、MySQL、HBase数据互导

环境准备

    //启动mysql服务
    $ service mysql start
    //启动Hadoop
    $ cd /usr/local/hadoop
    $ sbin/start-all.sh
    //查看Hadoop启动的进程
    $ jps
    //启动Hive
    $ cd /usr/local/hive
    $ bin/hive
    //创建临时表
    hive> create table dblab.user_action(id STRING,uid STRING, item_id STRING, behavior_type STRING, item_category STRING, visit_date DATE, province STRING) COMMENT 'Welcome to xmu dblab!' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE;

创建完临时表后Hive会在HDFS文件系统中创建对应的数据文件,可以通过以下命令查看:

    cd /usr/local/hadoop
    ./bin/hdfs dfs -ls /usr/hive/warehouse/dblab.db/user_action

结果如下:

    -rwxr-xr-x   1 hadoop supergroup   15590786 2016-11-27 21:57 /user/hive/warehouse/dblab.db/user_action/000000_0

接下来将Hive中bigdata_user中的内容插入user_action:

    hive> insert overwrite table user_action select * from bigdata_user; 

使用Sqoop将数据从Hive导入MySQL中

首先在mysql中创建一个用来存放数据的表格:

    $ mysql -u root -p
    //显示所有数据库
    mysql> show databases;
    mysql> create database dblab;
    mysql> use dblab;
    mysql> create table `dblab`.`user_action` (`id` varchar(50),`uid` varchar(50),`item_id` varchar(50),`behavior_type` varchar(10),`item_category` varchar(50), `visit_date` DATE,`province` varchar(20)) ENGINE=InnoDB DEFAULT CHARSET=utf8;//engine参数设置表格的默认存储引擎,后面的参数设置表格的编码
    mysql> exit

注意:要导入中文的话必须确保mysql的character_set_server的编码是utf8而不是latin1,可以通过命令show variables like "char%";查看。like "char%"表示要查看的变量长什么样子。修改方法:http://dblab.xmu.edu.cn/blog/install-mysql/。查看结果如下:

GopPZn.png

然后就可以用sqoop从Hive导入数据到mysql中了。

    cd /usr/local/sqoop
    ./bin/sqoop export --connect jdbc:mysql://localhost:3306/dblab --username root --password mysql --table user_action --export-dir '/user/hive/warehouse/dblab.db/user_action' --fields-terminated-by '\t';

代码解释:
export:从hive导入到mysql中
--connect jdbc:mysql://localhost:3306/dblab --username root --password mysql:连接mysql的地址以及mysql用户的账号密码
—table:mysql中的数据表格
—export-dir:导入源的路径,这里是HDFS上hive表格的路径
—field-terminated-by:行分隔符

执行完之后可以在mysql中查看导入的数据:

    $ mysql -u root -p
    mysql> use dblab;
    mysql> select * from user_action limit 10;

使用Sqoop从MySQL中导入数据到HBase

首先启动HBase服务和HBase的shell命令,然后在HBase中创建表格,最后使用sqoop导入数据

    cd /usr/local/hbase
    ./bin/start-hbase.sh
    ./bin/hbase shell
    hbase> create 'user_action',{NAME=>'f1',VERSIONS=5}

代码解释:HBase中的SQL语句跟mysql的差别比较大,属性用{}括起来,赋值符号是,而且不用以分号结束。NAME是列族名称,HBase是以列族为单位的一个NoSQL数据库,VERSIONS是历史版本保留数量。

    cd /usr/local/sqoop
    ./bin/sqoop import --connect jdbc:mysql://localhost:3306 --username root --password hadoop --table user_action --hbase-table user_action --column-family f1 --hbase-row-key id --hbase-create-table -m 1;

代码解释:
–hbase-table user_action #HBase中表名称
–column-family f1 #列簇名称
–hbase-row-key id #HBase 行键
–hbase-create-table #是否在不存在情况下创建表
-m 1 #启动 Map 数量

现在可以在HBase中查看导入的数据了:

    hbase> scan 'user_action',{LIMIT=>10}

注:上面的命令是显示前10行数据,但是执行结果看起来却远不止10行。是因为HBase中每行显示的不是一行记录,而是一个单元格。

使用HBase Java API把数据从本地导入HBase中

除了使用sqoop导入数据到HBase外,还可以用Java API把数据从本地导入到HBase中。Java代码如下:

    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.List;
     
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.hbase.HBaseConfiguration;
    import org.apache.hadoop.hbase.KeyValue;
    import org.apache.hadoop.hbase.client.Get;
    import org.apache.hadoop.hbase.client.HBaseAdmin;
    import org.apache.hadoop.hbase.client.HTable;
    import org.apache.hadoop.hbase.client.Put;
    import org.apache.hadoop.hbase.client.Result;
    import org.apache.hadoop.hbase.client.ResultScanner;
    import org.apache.hadoop.hbase.client.Scan;
    import org.apache.hadoop.hbase.util.Bytes;
     
    public class HBaseImportTest extends Thread {
        public Configuration config;
        public HTable table;
        public HBaseAdmin admin;
     
    		/**
    		* 构造函数:
    		* 构造一个实例需要指定这个HBase实例用到的表格和配置
    		**/
        public HBaseImportTest() {
            config = HBaseConfiguration.create();
    //      config.set("hbase.master", "master:60000");
    //      config.set("hbase.zookeeper.quorum", "master");
            try {
                table = new HTable(config, Bytes.toBytes("user_action"));
                admin = new HBaseAdmin(config);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
    		/**
    		* 主函数
    		**/
        public static void main(String[] args) throws Exception {
            if (args.length == 0) {       //第一个参数是该jar所使用的类,第二个参数是数据集所存放的路径
                throw new Exception("You must set input path!");
            }
     
            String fileName = args[args.length-1];  //输入的文件路径是最后一个参数
            HBaseImportTest test = new HBaseImportTest();
            test.importLocalFileToHBase(fileName);
        }
    	 
    		/**
    		* 创建一个缓冲阅读器,逐行读取文件内容,将它上传到HBase中。结束时关闭缓冲阅读器和HBase表格,然后打印出执行时间。
    		**/
        public void importLocalFileToHBase(String fileName) {
            long st = System.currentTimeMillis();
            BufferedReader br = null;
            try {
                br = new BufferedReader(new InputStreamReader(new FileInputStream(
                        fileName)));
                String line = null;
                int count = 0;
                while ((line = br.readLine()) != null) {
                    count++;
                    put(line);
                    if (count % 10000 == 0)
                        System.out.println(count);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
     
                if (br != null) {
                    try {
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
     
                try {
                    table.flushCommits();
                    table.close(); // must close the client
                } catch (IOException e) {
                    e.printStackTrace();
                }
     
            }
            long en2 = System.currentTimeMillis();
            System.out.println("Total Time: " + (en2 - st) + " ms");
        }
     
    		/**
    		* 将每一行的内容分割后与列名称一起上传
    		**/
        @SuppressWarnings("deprecation")
        public void put(String line) throws IOException {
            String[] arr = line.split("\t", -1);
            String[] column = {"id","uid","item_id","behavior_type","item_category","date","province"};
     
            if (arr.length == 7) {
                Put put = new Put(Bytes.toBytes(arr[0]));// rowkey
                for(int i=1;i<arr.length;i++){
                    put.add(Bytes.toBytes("f1"), Bytes.toBytes(column[i]),Bytes.toBytes(arr[i]));
                }
                table.put(put); // put to server
            }
        }
     
    		/**
    		* 
    		**/
        public void get(String rowkey, String columnFamily, String column,
                int versions) throws IOException {
            long st = System.currentTimeMillis();
     
            Get get = new Get(Bytes.toBytes(rowkey));
            get.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column));
     
            Scan scanner = new Scan(get);
            scanner.setMaxVersions(versions);
     
            ResultScanner rsScanner = table.getScanner(scanner);
     
            for (Result result : rsScanner) {
                final List<KeyValue> list = result.list();
                for (final KeyValue kv : list) {
                    System.out.println(Bytes.toStringBinary(kv.getValue()) + "\t"
                            + kv.getTimestamp()); // mid + time
                }
     
            }
            rsScanner.close();
     
            long en2 = System.currentTimeMillis();
            System.out.println("Total Time: " + (en2 - st) + " ms");
        }
     
    }

把上面代码打包成jar包,放到/usr/local/bigdatacase/hbase/目录下,然后在HBase中创建一个user_action表格,就可以用下面命令导入数据了。

/usr/local/hadoop/bin/hadoop jar /usr/local/bigdatacase/hbase/ImportHBase.jar HBaseImportTest /usr/local/bigdatacase/dataset/user_action.output

利用R语言进行数据可视化分析

R语言和相关依赖库的安装、数据准备

    $ sudo apt-get install r-base
    //进入R语言:
    $ R
    //退出R语言:
    > q()

安装依赖库:

    > install.package('RMySQL')
    > install.package('gglot2')
    > install.package('devtools')
    > devtools::install_github('taiyun/recharts')

代码解释:
包的名称用单引号或者双引号包起来都可以。RMySQL是一个提供了访问MySQL数据库的R语言程序接口;ggplotrecharts是提供绘图可视化的库。

安装R语言依赖包的过程中可能会有以下错误:

    Configuration failed because libmysqlclient was not found. Try installing:
     * deb: libmariadb-client-lgpl-dev (Debian, Ubuntu 16.04)
            libmariadbclient-dev (Ubuntu 14.04)
     * rpm: mariadb-devel | mysql-devel (Fedora, CentOS, RHEL)
     * csw: mysql56_dev (Solaris)
     * brew: mariadb-connector-c (OSX)
    .................
    ERROR: configuration failed for package ‘RMySQL’
    * removing ‘/home/hadoop/R/x86_64-pc-linux-gnu-library/3.3/RMySQL’
    
    下载的程序包在
        ‘/tmp/RtmpvEArxz/downloaded_packages’里
    Warning message:
    In install.packages("RMySQL") : 安装程序包‘RMySQL’时退出狀態的值不是0

这是由于用户系统所拥有的构件不一定都齐全,这里提示缺少libmysqlclient ,所以只需要按照提示在Linux中安装即可。如下:

sudo apt-get install libmariadb-client-lgpl-dev

数据准备

在Linux系统中新建另外一个终端,然后执行下面命令启动MySQL数据库:

$ service mysql start
$ mysql -u root -p

mysql> use dblab;

再在R语言中创建表格并导入:

    //查询R中的命令,如sort
    ?sort
    
    library(RMySQL)//使用RMySQL库
    conn <- dbConnect(MySQL(),dbname='dblab',username='root',password='mysql',host='127.0.0.1',port=3306)//R语言中的赋值符号是'<-'。连接MySQL,给出数据库名称、MySQL用户账号密码、地址和端口
    user_action <- dbGetQuenry(conn,'select * from user_action')//使用dbGetQuenry函数查询MySQL中的数据并赋值给R语言中的表。传入的参数是连接信息和MySQL查询语句

分析

分析消费者对商品的行为

    summary(user_action$behavior_type)
    //把消费者行为的数据类型转换为数值型
    summary(as.numeric(user_action$behavior_type))

代码解释:summary()函数可以得到样本数据类型和长度,如果样本是数值型,我们还能得到样本数据的最小值、最大值、四分位数以及均值信息。
R语言中查询某个表格中的某个属性的代码格式是:表名$属性名

绘柱状图:

    library(ggplot2)//导入ggplot库
    ggplot(user_action,aes(as.numeric(behavior_type)))+geom_histogram()

代码解释:ggplot()绘制时,创建绘图对象,即第一个图层,包含两个参数(数据与变量名称映射).变量名称需要被包含aes函数里面。ggplot2的图层与图层之间用“+”进行连接。ggplot2包中的geom_histogram()可以很方便的实现直方图的绘制。

分析被购买总量前十的商品机器购买总量

    temp <- subset(user_action,as.numeric(behavior_type)==4)
    count <- sort(table(temp$item_category),decreasing = T)
    print(count[1:10])

代码解释:首先创建一个只包含被购买商品的表格temp,然后对temp的中的商品种类进行从大到小的排序,再打印出前十的商品种类。

绘制散点图:

    result <- as.data.frame(count[1:10])
    ggplot(result,aes(Var1,Freq,col=factor(Var1)))+geom_point()

分析每年哪个月份购买数量最多:

    month <- substr(user_action$visit_date,6,7)//截取出月份
    user_action <- cbind(user_action,month)//增加一列月份的数据
    ggplot(user_action,aes(as.numeric(behavior_type),col=factor(month)))+geom_histogram()+facet_grid(.~month)

aes()函数中的col属性可以用来设置颜色。factor()函数则是把数值变量转换成分类变量,作用是以不同的颜色表示。如果不使用factor()函数,颜色将以同一种颜色渐变的颜色表现。 facet_grid(.~month)表示柱状图按照不同月份进行分区。
由于MySQL获取的数据中只有11月份和12月份的数据,所以上图只有显示两个表格。

分析哪个省份的消费者购买欲望最强:

    library(recharts)
    rel <- as.data.frame(table(temp$province))
    provinces <- rel$Var1
    x = c()
    for(n in provinces){
    x[length(x)+1] = nrow(subset(temp,(province==n)))}
    mapData <- data.frame(province=rel$Var1,count=x,stringsAsFactors=F)
    eMap(mapData,namevar=~province,datavar=~count)

绘出中国地图大致如下:

Go9QXQ.png

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值