课程1-hadoop-Zookeeper安装
Ububtu18.04安装Zookeeper3.7.1
环境与版本
这里采用的ubuntu18.04环境的基本配置为:
bash
hostname 为master
用户名为hadoop
静态IP为 192.168.100.3
网关为 192.168.100.2
防火墙已经关闭
/etc/hosts已经配置
全版本下载地址:
https://archive.apache.org/dist/zookeeper/
这里我选择3.7.1这个版本
https://archive.apache.org/dist/zookeeper/zookeeper-3.7.1/
下载到本地后,将apache-zookeeper-3.7.1-bin.tar.gz上传到ubuntu18.04的/home/hadoop/opt/app目录下,
该目录下的目录作用如下:
bash
bin目录 框架启动停止,客户端和服务端的
conf 配置文件信息
docs文档
lib 配置文档的依赖
standlone模式安装
解压缩与配置软连接
bash
hadoop@master:~$ cd /home/hadoop/opt/app/
# 解压缩
hadoop@master:~/opt/app$ tar -zxf apache-zookeeper-3.7.1-bin.tar.gz
查看当前目录结构:
bash
hadoop@master:~/opt/app$ pwd # 查看当前目录
/home/hadoop/opt/app
hadoop@master:~/opt/app$ ll
总用量 9120
drwxrwxr-x 6 hadoop hadoop 4096 11月 12 10:42 ./
drwxrwxr-x 3 hadoop hadoop 4096 11月 4 14:53 ../
drwxrwxr-x 6 hadoop hadoop 4096 11月 12 10:41 apache-zookeeper-3.7.1-bin/
-rw-rw-r-- 1 hadoop hadoop 9311744 11月 12 10:39 apache-zookeeper-3.7.1-bin.tar.gz
配置zookeeper的软连接
shell
# 软连接
hadoop@master:~/opt/app$ ln -s apache-zookeeper-3.7.1-bin zookeeper
创建存储目录与修改zoo.cfg文件
切换到~/opt/app/zookeeper,配置zookeeper的数据存储-data0目录
bash
hadoop@master:~/opt/app$ cd zookeeper # 切换到zookeeper中
hadoop@master:~/opt/app/zookeeper$ ls
bin conf docs lib LICENSE.txt NOTICE.txt README.md README_packaging.txt
hadoop@master:~/opt/app/zookeeper$ mkdir data0 # 创建data0
hadoop@master:~/opt/app/zookeeper$ ls
bin conf data0 docs lib LICENSE.txt NOTICE.txt README.md README_packaging.txt
进入~/opt/app/zookeeper/conf目录下,复制zoo_sample.cfg为zoo.cfg,
bash
hadoop@master:~/opt/app/zookeeper$ cd conf/
hadoop@master:~/opt/app/zookeeper/conf$ ls
configuration.xsl log4j.properties zoo_sample.cfg
hadoop@master:~/opt/app/zookeeper/conf$ cp zoo_sample.cfg zoo.cfg #复制zoo.cfg
编辑zoo.cfg
shell
hadoop@master:~/opt/app/zookeeper/conf$ vi zoo.cfg # 编辑zoo.cfg文件,编辑内容如下:
# dataDir=/tmp/zookeeper 注释掉这句默认配置,然后添加下面的配置
dataDir=/home/hadoop/opt/app/zookeeper/data0
# 在配置文件的最后面添加
server.1=master:2888:3888
# 如果是单节点的zookeeper集群部署可以配置多个server
#server.2=master:2889:3889
#server.3=master:2890:3890
配置zookeeper的环境变量
bash
hadoop@master:~/opt/app/zookeeper/conf$ vi ~/.bashrc
#这一步会打开bashrc文件,编辑内容如下:
export ZOOKEEPER_HOME=/home/hadoop/opt/app/zookeeper
export PATH=$ZOOKEEPER_HOME/bin:$PATH
hadoop@master:~/opt/app/zookeeper/conf$ source ~/.bashrc # 生效环境变量
启动与查看zk服务端(单机版本)
启动zk服务端(单机版本)
查看zk启动状态
bash
hadoop@master:~/opt/app/zookeeper/conf$ zkServer.sh status #查看zk启动状态
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.
启动zkServer
bash
hadoop@master:~/opt/app/zookeeper/conf$ zkServer.sh start #启动zkServer
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
查看zk启动状态
bash
hadoop@master:~/opt/app/zookeeper/conf$ zkServer.sh status #查看zk启动状态,单机启动为standalone模式
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: standalone
关闭zk服务端(单机版本)
bash
zkServer.sh start # 启动zk服务端
zkServer.sh stop # 关闭zk服务端
zkServer.sh status # 查看zk服务端状态
启动zk客户端
bash
hadoop@master:~/opt/app/zookeeper/conf$ zkCli.sh #启动zkCli,默认连接端口2181
Connecting to localhost:2181
...
...
...
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 1] help
ZooKeeper -server host:port cmd args
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path
delquota [-n|-b] path
get [-s] [-w] path
getAcl [-s] path
history
listquota path
ls [-s] [-w] [-R] path
ls2 path [watch]
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
rmr path
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b val path
stat [-w] path
sync path
Command not found: Command not found help
[zk: localhost:2181(CONNECTED) 2] quit
WATCHER::
WatchedEvent state:Closed type:None path:null
2021-11-12 11:05:29,497 [myid:] - INFO [main:ZooKeeper@1422] - Session: 0x1000029eae60000 closed
2021-11-12 11:05:29,497 [myid:] - INFO [main-EventThread:ClientCnxn$EventThread@524] - EventThread shut down for session: 0x1000029eae60000
hadoop@master:~/opt/app/zookeeper/conf$
配置伪分布式的Zookeeper
本小节的伪分布式集群部署是指在一台机器(master)上配置多个配置文件(zoo1.cfg,zoo2.cfg,zoo3.cfg),三个配置文件中设置不一样clientPort和dataDir,然后根据不同的配置文件来启动Zookeeper服务。
备注:本部分是在standlone已经完成安装的基础上进行的。
创建并生成各自的配置文件:
配置各个zk节点的配置文件,具体如下:
bash
hadoop@master:~/opt/app/zookeeper/conf$ pwd
/home/hadoop/opt/app/zookeeper/conf
hadoop@master:~/opt/app/zookeeper/conf$ cp zoo.cfg zoo1.cfg
hadoop@master:~/opt/app/zookeeper/conf$ cp zoo.cfg zoo2.cfg
hadoop@master:~/opt/app/zookeeper/conf$ cp zoo.cfg zoo3.cfg
分布修改这三个配置文件:
zoo1.cfg 配置文件
bash
# dataDir=/tmp/zookeeper 注释掉这句默认配置,然后修改下面的配置
dataDir=/home/hadoop/opt/app/zookeeper/data1
# clientPort=2181 注释掉15行这句话,把这句内容放在文件尾部
clientPort=2181
# server.1=master:2888(数据同步端口):3888(Leader选举端口)
server.1=master:2888:3888
server.2=master:2889:3889
server.3=master:2890:3890
zoo2.cfg 配置文件
bash
# dataDir=/tmp/zookeeper 注释掉这句默认配置,然后修改下面的配置
dataDir=/home/hadoop/opt/app/zookeeper/data2
# clientPort=2181 注释掉15行这句话,把这句内容放在文件尾部
clientPort=2182
# server.1=master:2888(数据同步端口):3888(Leader选举端口)
server.1=master:2888:3888
server.2=master:2889:3889
server.3=master:2890:3890
zoo3.cfg 配置文件
bash
# dataDir=/tmp/zookeeper 注释掉这句默认配置,然后修改下面的配置
dataDir=/home/hadoop/opt/app/zookeeper/data3
# clientPort=2183 注释掉15行这句话,把这句内容放在文件尾部
clientPort=2183
# server.1=master:2888(数据同步端口):3888(Leader选举端口)
server.1=master:2888:3888
server.2=master:2889:3889
server.3=master:2890:3890
server.A=B:C:D中A是一个数字,表示这个是第几号服务器,B是这个服务器的IP地址,C表示这个服务器与集群中的Leader服务器交换信息的端口,D表示集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。对于伪分布集群的配置方式,由于B都是一样,需要为不同的Zookeeper服务通信端口分配不同的端口号。
在各个data目录下创建myid文件,并存入当前服务器的编号,如下:
bash
hadoop@master:~/opt/app/zookeeper$ pwd
/home/hadoop/opt/app/zookeeper
hadoop@master:~/opt/app/zookeeper$ touch data1/myid
hadoop@master:~/opt/app/zookeeper$ touch data2/myid
hadoop@master:~/opt/app/zookeeper$ touch data3/myid
hadoop@master:~/opt/app/zookeeper$ echo 1 > data1/myid
hadoop@master:~/opt/app/zookeeper$ echo 2 > data2/myid
hadoop@master:~/opt/app/zookeeper$ echo 3 > data3/myid
启动并测试Zookeeper伪分布式集群
依次启动Zookeeper服务,在启动的时候,选举算法依次投票,那么Leader
服务就是2号配置文件启动的服务。其他的节点服务都是Fllower,当启动第一台服务器的时候查看状态status是不可用的,因为集群中节点未在半数以上。集群中奇数和偶数对故障的容忍度是一致的,所以建议配置奇数个Zookeeper节点。
启动zkServer.sh并指定配置文件为zoo1.cfg
bash
hadoop@master:~/opt/app/zookeeper$ zkServer.sh start /home/hadoop/opt/app/zookeeper/conf/zoo1.cfg # 通过zoo1.cfg启动zkServer
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/conf/zoo1.cfg
Starting zookeeper ... STARTED
hadoop@master:~/opt/app/zookeeper$ zkServer.sh status /home/hadoop/opt/app/zookeeper/conf/zoo1.cfg # 查看通过zoo1.cfg启动的zkServer状态
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/conf/zoo1.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.
启动zkServer.sh并指定配置文件为zoo2.cfg
bash
hadoop@master:~/opt/app/zookeeper$ zkServer.sh start /home/hadoop/opt/app/zookeeper/conf/zoo2.cfg # 通过zoo2.cfg启动zkServer
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/conf/zoo2.cfg
Starting zookeeper ... STARTED
hadoop@master:~/opt/app/zookeeper$ zkServer.sh status /home/hadoop/opt/app/zookeeper/conf/zoo2.cfg # 查看通过zoo2.cfg启动的zkServer状态,为leader
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/conf/zoo2.cfg
Client port found: 2182. Client address: localhost.
Mode: leader
启动zkServer.sh并指定配置文件为zoo3.cfg
bash
hadoop@master:~/opt/app/zookeeper$ zkServer.sh start /home/hadoop/opt/app/zookeeper/conf/zoo3.cfg # 通过zoo3.cfg启动zkServer
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/conf/zoo3.cfg
Starting zookeeper ... STARTED
hadoop@master:~/opt/app/zookeeper$ zkServer.sh status /home/hadoop/opt/app/zookeeper/conf/zoo3.cfg # 查看通过zoo3.cfg启动的zkServer状态
ZooKeeper JMX enabled by default
Using config: /home/hadoop/opt/app/zookeeper/conf/zoo3.cfg
Client port found: 2183. Client address: localhost.
Mode: follower
目前看到zoo2.cfg的进程为leader节点。
如下图:
此时使用命令jps查看所有进程:
bash
hadoop@master:~/opt/app/zookeeper$ jps
4833 QuorumPeerMain
5060 Jps
4726 QuorumPeerMain
4607 QuorumPeerMain
客户端连接Zookeeper服务节点,则使用如下命令:
bash
hadoop@master:~/opt/app/zookeeper$ zkCli.sh -server localhost:2181
Connecting to localhost:2181
#退出使用quit
centos安装Zookeeper3.7.1
这里采用的centos7.6环境的基本配置为:
bash
hostname 为node1
用户名为root
静态IP为 192.168.100.3
网关为 192.168.100.2
防火墙已经关闭
/etc/hosts已经配置
全版本下载地址:
https://archive.apache.org/dist/zookeeper/
这里我选择3.7.1这个版本
https://archive.apache.org/dist/zookeeper/zookeeper-3.7.1/
下载到本地后,将apache-zookeeper-3.7.1-bin.tar.gz上传到ubuntu18.04的/home/hadoop/opt/app目录下,
该目录下的目录作用如下:
bash
bin目录 框架启动停止,客户端和服务端的
conf 配置文件信息
docs文档
lib 配置文档的依赖
基于centos7.6伪分布模式安装
centos7.6安装zookeeper的过程与ubuntu安装zookeeper的过程完全一致。下面提供具体过程。
上传解压修改文件名
上传apache-zookeeper-3.7.1-bin.tar.gz 到/opt/software目录下,并对压缩包进行解压
[root@node1 ~]# cd /opt/software/
# 解压缩
[root@node1 ~]# tar -zxvf apache-zookeeper-3.7.1-bin.tar.gz
# 修改文件名
[root@node1 ~]# mv apache-zookeeper-3.7.1-bin zookeeper
# 创建zkdata目录
[root@node1 ~]# cd /opt/software/zookeeper
[root@node1 ~]# mkdir zkdata
复制zookeeper安装目录
复制zookeeper目录到/opt/module目录下,并复制3份,命名为001-003
cd /opt/software
cp -r zookeeper /opt/module/zookeeper001
cp -r zookeeper /opt/module/zookeeper002
cp -r zookeeper /opt/module/zookeeper003
创建并配置zoo.cfg配置文件
修改zookeeper001配置文件
首先把zookeeper001/conf下的的zoo_sample.cfg文件复制为zoo.cfg
bash
cd /opt/module/zookeeper001/conf
cp zoo_sample.cfg zoo.cfg
修改zoo.cfg配置文件
bash
vim zoo.cfg
修改配置如下
bash
# 第1步:设置数据持久化目录
dataDir=/opt/module/zookeeper001/zkdata
# 设置客户端连接当前ZooKeeper服务使用的端口号
clientPort=2181
# 设置ZooKeeper集群中每个ZooKeeper服务的地址及端口号
server.1=node1:2888:3888
server.2=node1:2889:3889
server.3=node1:2890:3890
在zookeeper001/zkdata下创建myid文件,内容为1
bash
echo 1 > /opt/module/zookeeper001/zkdata/myid
修改zookeeper002配置文件
首先把zookeeper002/conf下的的zoo_sample.cfg文件复制为zoo.cfg
bash
cd /opt/module/zookeeper002/conf
cp zoo_sample.cfg zoo.cfg
修改zoo.cfg配置文件
bash
vim zoo.cfg
修改配置如下
bash
# 第1步:设置数据持久化目录
dataDir=/opt/module/zookeeper002/zkdata
# 设置客户端连接当前ZooKeeper服务使用的端口号
clientPort=2182
# 设置ZooKeeper集群中每个ZooKeeper服务的地址及端口号
server.1=node1:2888:3888
server.2=node1:2889:3889
server.3=node1:2890:3890
在zookeeper002/zkdata下创建myid文件,内容为2
bash
echo 2 > /opt/module/zookeeper002/zkdata/myid
修改zookeeper003配置文件
首先把zookeeper003/conf下的的zoo_sample.cfg文件复制为zoo.cfg
bash
cd /opt/module/zookeeper003/conf
cp zoo_sample.cfg zoo.cfg
修改zoo.cfg配置文件
bash
vim zoo.cfg
修改配置如下
bash
# 第1步:设置数据持久化目录
dataDir=/opt/module/zookeeper003/zkdata
# 设置客户端连接当前ZooKeeper服务使用的端口号
clientPort=2183
# 设置ZooKeeper集群中每个ZooKeeper服务的地址及端口号
server.1=node1:2888:3888
server.2=node1:2889:3889
server.3=node1:2890:3890
在zookeeper003/zkdata下创建myid文件,内容为1
bash
echo 3 > /opt/module/zookeeper001/zkdata/myid
启动并测试Zookeeper伪分布式集群
依次启动Zookeeper服务,在启动的时候,选举算法依次投票,那么Leader
服务就是2号配置文件启动的服务。其他的节点服务都是Fllower,当启动第一台服务器的时候查看状态status是不可用的,因为集群中节点未在半数以上。集群中奇数和偶数对故障的容忍度是一致的,所以建议配置奇数个Zookeeper节点。
启动zookeeper001下的zkServer.sh
bash
[root@node1 module]# cd /opt/module/
[root@node1 module]# ./zookeeper001/bin/zkServer.sh start # 启动zkServer
输出为:
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper001/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
查看zkServer状态
bash
[root@node1 module]# ./zookeeper001/bin/zkServer.sh status # 查看zkServer状态
输出为:
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper001/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.
启动zookeeper002下的zkServer.sh
bash
[root@node1 module]# cd /opt/module/
[root@node1 module]# ./zookeeper002/bin/zkServer.sh start # 启动zkServer
输出为:
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper002/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
查看zkServer状态
bash
[root@node1 module]# ./zookeeper002/bin/zkServer.sh status # 查看zkServer状态
输出为:
Using config: /opt/module/zookeeper002/bin/../conf/zoo.cfg
Client port found: 2182. Client address: localhost. Client SSL: false.
Mode: leader
启动zookeeper003下的zkServer.sh
bash
[root@node1 module]# cd /opt/module/
[root@node1 module]# ./zookeeper003/bin/zkServer.sh start # 启动zkServer
输出为:
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper003/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
查看zkServer状态
bash
[root@node1 module]# ./zookeeper003/bin/zkServer.sh status # 查看zkServer状态
输出为:
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper003/bin/../conf/zoo.cfg
Client port found: 2183. Client address: localhost. Client SSL: false.
Mode: follower
启动后,myid值为2的zookeeper002下的称为了leader。
课程2-数据导入与预处理-数据变换
主要是对数据进行规范化的操作,将数据转换成"适当的"格式,以适用于挖掘任务及算法的需要。
5.1数据变换方法
数据变换的常见处理方式包括:
数据标准化处理
数据离散化处理
数据泛化处理
在对数据进行分析或挖掘之前,数据必须满足一定的条件:
比如方差分析时要求数据具有正态性 、方差齐性 、独立性 、无偏性 ,需进行诸如平方根 、对数 、平方根反正弦 操作,实现从一种形式到另一种"适当"形式的变换,以适用于分析或挖掘的需求,这一过程就是数据变换。
数据变换主要是从数据中找到特征表示,通过一些转换方法减少有效变量的数目或找到数据的不变式,常见的操作可以分为数据标准化处理、数据离散化处理和数据泛化处理三类。
数据标准化处理
数据标准化处理是将数据按照一定的比例缩放,使之投射到一个比较小的特定区间。
最小-最大标准化(规范化)
最小-最大规范化:也称为离差标准化,是对原始数据的线性变换,使结果值映射到[0,1]之间。
转换函数如:
其中 max为样本数据的最大值,min为样本数据的最小值。max-min为极差。
以一个例子说明标准化的计算过程。
均值标准化(规范化)
零-均值规范化:也叫标准差标准化,经过处理的数据的平均数为0,标准差为1。转化函数为:
其中 x ‾ \overline{x} x为原始数据的均值, σ \sigma σ为原始数据的标准差。
小数定标标准化(规范化)
小数定标规范化:通过移动属性值的小数位数,将属性值映射到[-1,1]之间,移动的小数位数取决于属性值绝对值的最大值。转化函数为:移动数据的小数点,使数据映射到[-1,1]。
转换函数如下:
x ∗ = x 1 0 k x^{\ast }=\dfrac{x}{10^{k}} x∗=10kx
数据离散化处理
一些数据挖掘算法,特别是某些分类算法,要求数据是分类属性形式,如ID3算法、Apriori算法等。这样,常常需要将连续属性变换成分类属性,即连续属性离散化。
数据离散化处理一般是在数据的取值范围内设定若干个离散的划分点,将取值范围划分为若干离散化的区间,分别用不同的符号或整数值代表落在每个子区间的数值。
连续属性变换成分类属性涉及两个子任务:决定需要多少个分类变量 ,以及确定如何将连续属性值映射到这些分类值。
等宽法
等宽法将属性的值域从最小值到最大值划分成具有相同宽度的区间,具体划分多少个区间由数据本身的特点决定,或者由具有业务经验的用户指定
等频法
等频法将相同数量的值划分到每个区间,保证每个区间的数量基本一致。
等宽法和等频法虽然简单,但是都需要人为地规定划分区间的个数。等宽法会不均匀地将属性值分到各个区间,导致有些区间包含较多数据,有些区间包含较少数据,不利于挖掘后期决策模型的建立。
数据泛化处理(分层)
数据泛化处理指用高层次概念取代低层次概念的数据。例如,年龄是一个低层次的概念,它经过泛化处理后会变成诸如青年、中年等高层次的概念。
5.4 轴向旋转
掌握pivot()和melt()方法的用法,可以熟练地使用这些方法实现轴向旋转操作
pivot方法
pivot()方法用于将DataFrame类对象的某一列数据转换为列索引,也叫透视方法。官网中对pivot()函数的描述如下:
Reshape data (produce a "pivot" table) based on column values. Uses unique values from specified index / columns to form axes of the resulting DataFrame. This function does not support data aggregation, multiple values will result in a MultiIndex in the columns.
基于列值重塑数据(生成一个"透视"表)。使用来自指定索引/列的唯一值来形成结果DataFrame的轴。此函数不支持数据聚合,多个值将导致列中的MultiIndex。
pivot()函数如下:
python
DataFrame.pivot(index=None, columns=None, values=None)
index:表示新生成对象的行索引,若未指定说明使用现有对象的行索引。
columns:表示新生成对象的列索引。
values :表示填充新生成对象的值。
要想了解pivot()函数,可以先了解下pivot_table()函数。pivot_table()函数是pivot()函数的泛化,pivot_table函数允许值的聚合。
pivot_table透视的过程如下图:
假设某商店记录了5月和6月活动期间不同品牌手机的促销价格,保存到以日期、商品名称、价格为列标题的表格中,若对该表格的商品名称列进行轴向旋转操作,即将商品名称一列的唯一值变换成列索引,将出售日期一列的唯一值变换成行索引。
示例代码如下:
构建DataFrame:
python
import pandas as pd
df_obj = pd.DataFrame({'商品名称': ['荣耀9X','小米6x','OPPO A1',
'荣耀9X','小米6x','OPPO A1'],
'出售日期': ['5月25日', '5月25日','5月25日',
'6月18日','6月18日', '6月18日'],
'价格(元)': [999, 1399, 1399, 800, 1200, 1250]})
df_obj
输出为:
将出售日期一列的唯一数据变换为行索引,商品一列的唯一数据变换为列索引:
python
# 将出售日期一列的唯一数据变换为行索引,商品一列的唯一数据变换为列索引
new_df = df_obj.pivot(index='出售日期', columns='商品名称',values='价格(元)')
new_df
输出为:
melt方法
melt()是pivot()的逆操作方法,用于将DataFrame类对象的列索引转换为一行数据。
python
DataFrame.melt(id_vars=None, value_vars=None, var_name=None,
value_name='value', col_level=None, ignore_index=True)
id_vars:表示无需被转换的列索引。
value_vars:表示待转换的列索引,若剩余列都需要转换,则忽略此参数。
var_name:表示自定义的列索引。
value_name:表示自定义的数据所在列的索引。
ignore_index:表示是否忽略索引,默认为True。
示例代码如下:
查看初始数据
python
new_df
输出为:
# 将列索引转换为一行数据:
python
# 将列索引转换为一行数据
new_df.melt(value_name='价格(元)', ignore_index=False)
输出为:
5.3 分组与聚合
分组与聚合是常见的数据变换操作
分组指根据分组条件(一个或多个键)将原数据拆分为若干个组;
聚合指任何能从分组数据生成标量值的变换过程,这一过程中主要对各分组应用同一操作,并把操作后所得的结果整合到一起,生成一组新数据。
下面通过一个例子说明分组聚合的过程:
掌握分组与聚合的过程,可以熟练地groupby()、agg()、transfrom()和apply()方法实现分组与聚合操作
分组操作groupby()(5.3.3)
分组操作
pandas中使用groupby()方法根据键将原数据拆分为若干个分组。
python
groupby(by=None, axis=0, level=None, as_index=True, sort=True,
group_keys=True, squeeze=<object object>, observed=False, dropna=True)
by:表示分组的条件,可以取值为字符串、列表、字典或Series、函数等。
axis:表示分组操作的轴编号,可以是0或1。该参数的默认值为0,代表沿列方向操作。
level:表示标签索引所在的级别,默认为None。
as_index:表示聚合后新数据的索引是否为分组标签的索引,默认为True。
sort:表示是否对分组索引进行排序,默认为True。
group_keys:表示是否显示分组标签的名称,默认为True。
使用pandas的groupby()方法拆分数据后会返回一个GroupBy类的对象,该对象是一个可迭代对象,它里面包含了每个分组的具体信息,但无法直接被显示。
DataFrameGroupBy和SeriesGroupBy都是GroupBy的子类。
若DataFrame类对象调用groupby()方法,会返回一个DataFrameGroupBy类的对象。
若Series类对象调用groupby()方法,会返回一个SeriesGroupBy类的对象。
分组操作案例:
分组初始化
python
# 分组初始化
import pandas as pd
df_obj = pd.DataFrame({"key":["C", "B", "C", "A", "B", "B", "A", "C", "A"],
"data":[2, 4, 6, 8, 10, 1, 3, 5, 7]})
# 根据key列对df_obj进行分组
groupby_obj = df_obj.groupby(by="key")
groupby_obj
输出为:
GroupBy对象不可查看,可以遍历过去其中数据
遍历DataFrameGroupBy类的对象:
python
# 遍历DataFrameGroupBy类的对象
for group in groupby_obj:
print(group)
print("-"*10)
输出为:
通过列表生成器 获取DataFrameGroupBy的数据:
python
# 通过列表生成器 获取DataFrameGroupBy的数据
result = dict([x for x in groupby_obj])['A'] # 字典中包含多个DataFrame
result
输出为:
通过groups获取内容
python
# 查看全部分组内容
df_obj.groupby(["key"]).groups
输出为:
查看指定分组内容
python
# 查看指定分组内容
df_obj.groupby(["key"]).get_group(("A"))
输出为:
分组+内置聚合
分组+自定义聚合:
python
# 分组+自定义聚合
import pandas as pd
df_obj = pd.DataFrame({"key":["C", "B", "C", "A", "B", "B", "A", "C", "A"],
"data":[2, 4, 6, 8, 10, 1, 3, 5, 7]})
print(df_obj)
df_obj[['key','data']].groupby(by="key").max()
输出为:
分组+内置聚合,取消分组键做索引
python
# 取消索引 按照上一题要求进行分组,但不使用 key 做为索引
df_obj[['key','data']].groupby(by="key", as_index=False).max()
输出为:
分组+内置函数+排序
python
# 排序 分组 聚合后 排序
df_obj[['key','data']].groupby(by="key").max().sort_values('data',ascending=False)
输出为:
分组+内置函数+频率统计
python
# 频率 计算不同key,不同data出现的次数
pd.DataFrame(df_obj.groupby("key")['data'].value_counts())
输出为:
聚合操作 (5.3.4 )
pandas中可通过多种方式实现聚合操作,除前面介绍过的内置统计方法之外,还包括agg()、transfrom()和apply()方法。
初始化聚合所需的DF:
python
# 初始化分组DF
import pandas as pd
df_obj = pd.DataFrame({'a': [0, 6, 12, 18, 24, 30],
'b': [1, 7, 13, 19, 25, 31],
'c': [1, 8, 14, 20, 26, 32],
'd': [2, 9, 15, 21, 27, 33],
'e': [2, 10, 16, 22, 28, 34],
'f': [2, 2, 2, 3, 3, 2]})
df_obj
输出为:
查看DF的值:
python
# 根据列表对df_obj进行分组,列表中相同元素对应的行会归为一组
groupby_obj = df_obj.groupby(by=['A', 'A', 'B', 'B', 'A', 'B'])
# groupby_obj.groups
print(dict([x for x in groupby_obj]))
print('-'*10)
for (key,value) in dict([x for x in groupby_obj]).items():
print(key)
print(value)
输出为:
agg()方法
agg()方法既接收内置统计方法,又接收自定义函数,甚至可以同时运用多个方法或函数,或给各列分配不同的方法或函数,能够对分组应用灵活的聚合操作。
传入自定义函数:
python
for (key,value) in dict([x for x in groupby_obj]).items():
print(key)
print(value)
# 定义求极差的函数
def my_range(arr):
return arr.max()-arr.min()
groupby_obj.agg(my_range) # 使用agg()方法聚合分组数据
输出为:
指定列聚合
python
# 使用agg()方法聚合分组中指定列的数据
groupby_obj.agg({'a':'max', 'c':'sum', 'e': my_range})
输出为:
在使用agg方法中,还经常使用重置索引+重命名的方式:
python
# 初始化分组DF
import pandas as pd
df_obj = pd.DataFrame({'a': [0, 1, 2, 3, 4, 5],
'b': [1, 7, 13, 19, 25, 31],
'c': [1, 8, 14, 20, 26, 32],
'd': [2, 9, 15, 21, 27, 33],
'e': [2, 10, 16, 22, 28, 34],
'f': [2, 2, 2, 3, 3, 2]})
print(df_obj)
df_obj.groupby(by='f').agg({'a':'count'})
输出为:
会发现,经过agg聚合后,分组键做了索引,聚合之后的a列的列名为a,这个列名会与原有的列名冲突,换成a_count比较合适,方法如下:
python
df_obj.groupby(by='f').agg({'a':'count'}).reset_index().rename(columns={'a': 'a_count'})
输出为:
transfrom()方法
transfrom()方法能对分组应用灵活的运算操作,同时可使聚合前与聚合后的数据结构保持一致。
初始化DF
python
# 初始化分组DF
import pandas as pd
df_obj = pd.DataFrame({'a': [0, 6, 12, 18, 24, 30],
'b': [1, 7, 13, 19, 25, 31],
'c': [1, 8, 14, 20, 26, 32],
'd': [2, 9, 15, 21, 27, 33],
'e': [2, 10, 16, 22, 28, 34],
'f': [2, 2, 2, 3, 3, 2]})
df_obj
输出为:
基于transform求最大值:
python
df_obj['a_max'] = df_obj[['a','f']].groupby(by=['f']).transform('max')
df_obj
输出为:
如果不提前选取列,会生成同等结果的返回结果:
python
del df_obj['a_max']
df_obj.groupby(by=['f']).transform('max')
输出如下:
apply()方法
apply()方法既能直接接收内置方法,又可以接收自定义的函数。
与前几种聚合方式相比,使用apply()方法聚合数据的操作更灵活,它可以代替前两种聚合完成基础操作,另外也可以解决一些特殊聚合操作。
python
apply(func, *args, **kwargs)
func:表示应用于各分组的函数或方法。
*args和**kwargs :表示传递给func的位置参数或关键字参数。
案例如下:
python
# 初始化分组DF
import pandas as pd
df_obj = pd.DataFrame({'a': [0, 6, 12, 18, 24, 30],
'b': [1, 7, 13, 19, 25, 31],
'c': [1, 8, 14, 20, 26, 32],
'd': [2, 9, 15, 21, 27, 33],
'e': [2, 10, 16, 22, 28, 34],
'f': [2, 2, 2, 3, 3, 2]})
print(df_obj)
# 自定义函数,用于计算每个数据除以10的余数
def div_hun(df):
return df.iloc[:, :] % 10
df_obj.groupby(by=['f']).apply(div_hun)
输出为:
filter()方法
通过filter也可过滤分组后的数据:
python
# 初始化分组DF
import pandas as pd
df_obj = pd.DataFrame({'a': [0, 6, 12, 18, 24, 30],
'b': [1, 7, 13, 19, 25, 31],
'c': [1, 8, 14, 20, 26, 32],
'd': [2, 9, 15, 21, 27, 33],
'e': [2, 10, 16, 22, 28, 34],
'f': [2, 2, 2, 3, 3, 2]})
print(df_obj)
df_obj.groupby('f').filter(lambda x: x['a'].max() >26)
输出为:
哑变量与面元切分
哑变量处理(5.5.1)
在数据分析或挖掘中,一些算法模型要求输入以数值类型表示的特征,但代表特征的数据不一定都是数值类型的,其中一部分是类别型的,例如,受教育程度表示方式有大学、研究生、博士等类别,这些类别均为非数值类型的数据。为了将类别类型的数据转换为数值类型的数据,类别类型的数据在被应用之前需要经过"量化"处理,从而转换为哑变量。
什么是哑变量
哑变量又称虚拟变量、名义变量等,它是人为虚设的变量,用来反映某个变量的不同类别,常用的取值为0和1。需要说明的是,0和1并不代表数量的多少,而代表不同的类别。
假设变量"职业"有司机、学生、导游、工人、教师共5个类别,这5个类别分别有0和1两种取值,0代表非此种类别,1代表此种类别。
实现哑变量的方法:
pandas中使用get_dummies()函数对类别数据进行哑变量处理,并在处理后返回一个哑变量矩阵。
python
get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False,
columns=None, sparse=False, drop_first=False, dtype=None)
data:表示待处理的类别数据,可以是数组、DataFrame类或Series类对象。
prefix:表示列索引名称的前缀,默认为None。
prefix_sep:表示附加前缀的分隔符,默认为"_"。
columns:表示哑变量处理的列索引名称,默认为None。
初始化数据:
python
# 初始化DF
import pandas as pd
position_df = pd.DataFrame({'职业': ['工人', '学生', '司机', '教师', '导游']})
position_df
输出为:
哑变量处理, 并给哑变量添加前缀:
python
# 哑变量处理, 并给哑变量添加前缀
result = pd.get_dummies(position_df, prefix=['col'])
result
输出为:
面元划分(5.5.2 )
掌握cut()函数的用法,可以熟练地使用过该函数实现面元划分操作
面元划分是指数据被离散化处理,按一定的映射关系划分为相应的面元(可以理解为区间),只适用于连续数据。连续数据又称连续变量,指在一定区间内可以任意取值的数据,该类型数据的特点是数值连续不断,相邻两个数值可作无限分割。
pandas中使用cut()函数能够实现面元划分操作,cut()函数会采用等宽法对连续型数据进行离散化处理。
python
cut(x, bins, right=True, labels=None, retbins=False, precision=3,
include_lowest=False, duplicates='raise', ordered=True)
x:表示面元划分的连续数据,可以取值为一维数组或Series类对象。
bins:表示划分面元的依据。
right:表示右端点是否为闭区间,默认为True。
precision:表示区间标签的精度,默认为3。
include_lowest:表示是否包含区间的左端点,默认为False。
cut()函数会返回一个Categorical类对象,该对象可以被看作一个包含若干个面元名称的数组,通过categories属性可以获取所有的分类,即每个数据对应的面元。
案例如下:
python
import pandas as pd
ages = pd.Series([19, 21, 25, 55, 30, 45, 52, 46, 20])
bins = [0, 18, 30, 40, 50, 100]
# 使用cut函数划分年龄区间
cuts = pd.cut(ages, bins)
cuts
输出为:
Pandas与SQL对比
参考文档如下