数据分析个人笔记

数据分析

一、 Jupyter Notebook

Jupyter Notebook 有两种键盘输入模式。编辑模式,允许你往单元中键入代码或文本;这时的单元框线是绿色的。命令模式,键盘输入运行程序命令;这时的单元框线是灰色。

1、 命令模式

(按键 Esc 开启)

  • Enter : 转入编辑模式
  • Shift-Enter : 运行本单元,选中下个单元
  • Ctrl-Enter : 运行本单元
  • Alt-Enter : 运行本单元,在其下插入新单元
  • Y : 单元转入代码状态
  • M :单元转入markdown状态
  • R : 单元转入raw状态
  • 1 : 设定 1 级标题
  • 2 : 设定 2 级标题
  • 3 : 设定 3 级标题
  • 4 : 设定 4 级标题
  • 5 : 设定 5 级标题
  • 6 : 设定 6 级标题
  • Up : 选中上方单元
  • K : 选中上方单元
  • Down : 选中下方单元
  • J : 选中下方单元
  • Shift-K : 扩大选中上方单元
  • Shift-J : 扩大选中下方单元
  • A : 在上方插入新单元
  • B : 在下方插入新单元
  • X : 剪切选中的单元
  • C : 复制选中的单元
  • Shift-V : 粘贴到上方单元
  • V : 粘贴到下方单元
  • Z : 恢复删除的最后一个单元
  • D,D : 删除选中的单元
  • Shift-M : 合并选中的单元
  • Ctrl-S : 文件存盘
  • S : 文件存盘
  • L : 转换行号
  • O : 转换输出
  • Shift-O : 转换输出滚动
  • Esc : 关闭页面
  • Q : 关闭页面
  • H : 显示快捷键帮助
  • I,I : 中断Notebook内核
  • 0,0 : 重启Notebook内核
  • Shift : 忽略
  • Shift-Space : 向上滚动
  • Space : 向下滚动

2、 编辑模式

( Enter 键启动)

  • Tab : 代码补全或缩进
  • Shift-Tab : 提示
  • Ctrl-] : 缩进
  • Ctrl-[ : 解除缩进
  • Ctrl-A : 全选
  • Ctrl-Z : 复原
  • Ctrl-Shift-Z : 再做
  • Ctrl-Y : 再做
  • Ctrl-Home : 跳到单元开头
  • Ctrl-Up : 跳到单元开头
  • Ctrl-End : 跳到单元末尾
  • Ctrl-Down : 跳到单元末尾
  • Ctrl-Left : 跳到左边一个字首
  • Ctrl-Right : 跳到右边一个字首
  • Ctrl-Backspace : 删除前面一个字
  • Ctrl-Delete : 删除后面一个字
  • Esc : 进入命令模式
  • Ctrl-M : 进入命令模式
  • Shift-Enter : 运行本单元,选中下一单元
  • Ctrl-Enter : 运行本单元
  • Alt-Enter : 运行本单元,在下面插入一单元
  • Ctrl-Shift– : 分割单元
  • Ctrl-Shift-Subtract : 分割单元
  • Ctrl-S : 文件存盘
  • Shift : 忽略
  • Up : 光标上移或转入上一单元
  • Down :光标下移或转入下一单元

简单的魔法指令 %run 运行外部的python文件 %whos 查看声明了那些变量和函数 !ls 查看当前目录下的子文件和子目录 !pwd

二、numpy

前言:从图片认识numpy

#科学计算库
import numpy as np
#画图的,统计学使用的图片表达库 画饼图 折线图 直方图 箱图 极图  可以读取图片和显示图片
import matplotlib.pyplot as plt
#读取图片  图片3维数组  张量
#图片的小知识 彩色图片都是3维的,最后一个维度是RGB  和 黑白图片是二维的
#jpg 0-255,每个颜色以功能更有256种颜色表示法2^8      
#png 0-1  一共无限种类的颜色表示 索引png的颜色一般要比jpg鲜艳
gb1 = plt.imread('./guobin.jpg')
gb1
"""
array([[[ 67,  48,  31],[ 76,  57,  40],[ 77,  58,  41],...,[128, 146, 156],[141, 159, 169],[156, 174, 184]],[[ 71,  52,  35],[ 80,  61,  44],[ 80,  61,  44],...,[129, 147, 157],[139, 157, 167],[150, 168, 178]],[[ 77,  58,  41],[ 86,  67,  50],[ 86,  67,  50],...,[134, 152, 162],[139, 157, 167],[145, 163, 173]],...,[[ 83,  64,  86],[ 78,  56,  79],[ 75,  51,  75],...,[123,  86, 103],[127,  90, 107],[128,  91, 108]],[[ 81,  62,  84],[ 75,  56,  78],[ 75,  53,  76],...,[125,  91, 107],[131,  97, 113],[135, 101, 117]],[[ 84,  65,  87],[ 79,  60,  82],[ 79,  57,  80],...,[128,  96, 111],[135, 103, 118],[141, 109, 124]]], dtype=uint8)
"""
#png的图片显示、图片、资源类型
plt.imshow(gb1)#shape查看多维数组的形状,第一个值代表数组的行数,第二个值是列数量
gb1.shape

1、数据类型

#numeric python 数字化的python
#numpy中最重要的一个形式叫ndarray ,多维数组(列表):n:表示的是n个 d:dimension 维度 array 数组
#Python 本身支持的数值类型有:`int`(整型,python2 中存在 long 长整型)`float`(浮点型)`bool`(布尔型)`complex`(复数型)。
#而 Numpy 支持比 Python 本身更为丰富的数值类型,细分如下:
1. `bool`:布尔类型,1 个字节,值为 TrueFalse2. `int`:整数类型,通常为 int64 。
3. `intc`:与 C 里的 int 相同,通常为int64。=mysql bigint 2^64 金融业务中
4. `intp`:用于索引,通常为int64。
5. `int8`:字节(从 -128127) tinyint = 表示年龄最合适的数据类型 (tinyint 1字节 -2 ^7 ~ 2^7-1 (-128~127)6. `int16`:整数(从 -3276832767) smallint (smallint 2字节 -2 ^15 ~ 2^15-1 (-32768~32765))
7. `int32`:整数(从 -21474836482147483647intid比较合适 (int 4字节 -2 ^31~ 2^31-1 (-2147483648~2147483647)8. `int64`:整数(从 -92233720368547758089223372036854775807) bigint(bigint 8字节 -2 ^63 ~ 2^63-19. `uint8`:无符号整数(从 0255) unsigned
10. `uint16`:无符号整数(从 06553511. `uint32`:无符号整数(从 0429496729512. `uint64`:无符号整数(从 01844674407370955161513. `float`:float64 的简写。
14. `float16`:半精度浮点,5 位指数,10 位尾数
15. `float32`:单精度浮点,8 位指数,23 位尾数
16. `float64`:双精度浮点,11 位指数,52 位尾数
17. `complex`:complex128 的简写。
18. `complex64`:复数,由两个 32 位浮点表示。
19. `complex128`:复数,由两个 64 位浮点表示。
在 Numpy 中,上面提到的这些数值类型都被归于 `dtype(data-type)` 对象的实例。 
我们可以用 `numpy.dtype(object, align, copy)` 来指定数值类型。而在数组里面,可以用 `dtype=` 参数。

2、ndarray六个参数

>>shape:数组的形状。
>>dtype:数据类型。
buffer:对象暴露缓冲区接口。
offset:数组数据的偏移量。
>>strides:数据步长。
>>order:{'C''F'},以行或列为主排列顺序。

下面,我们来了解创建 ndarray 的一些方法。在 numpy 中,我们主要通过以下 5 种途径创建数组,它们分别是:

1.从 Python 数组结构列表,元组等转换
2.使用 np.arange、np.ones、np.zeros 等 numpy 原生方法。
3.从存储空间读取数组。
4.通过使用字符串或缓冲区从原始字节创建数组。
5.使用特殊函数,如 random。

1. 从列表或元组转换

在 numpy 中,我们使用 numpy.array 将列表或元组转换为 ndarray 数组。其方法为:

numpy.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0) 

其中,参数:

  • object:列表、元组等。
  • dtype:数据类型。如果未给出,则类型为被保存对象所需的最小类型。
  • copy:布尔来写,默认 True,表示复制对象。

下面,通过列表创建一个 ndarray 数组:

import numpy as np
list_ = [1,2,3,4,5,6]
type(list_)
"""
list
"""
#np.array()是将其它的类型强制转换为ndarray类型
type(np.array(list_))
"""
numpy.ndarray
"""

2.arange方法创建

除了直接使用 array 方法创建 ndarray,在 numpy 中还有一些方法可以创建一些有规律性的多维数。首先,我们来看一看 arange()。arange() 的功能是在给定区间内创建一系列均匀间隔的值。方法如下:

numpy.arange(start, stop, step, dtype=None)  

你需要先设置值所在的区间,这里为 ``[开始, 停止),你应该能发现这是一个半开半闭区间。然后,在设置step步长用于设置值之间的间隔。最后的可选参数dtype可以设置返回ndarray` 的值类型:

#arange  a=array  range() 仅仅只有ndarray可以使用 
#半闭区间
nd1 = np.arange(0,100,dtype=np.float32)
nd1.dtype
#dtype('float32')
nd1
#array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12.,
#       13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25.,
#       26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38.,
#      39., 40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51.,
#       52., 53., 54., 55., 56., 57., 58., 59., 60., 61., 62., 63., 64.,
#       65., 66., 67., 68., 69., 70., 71., 72., 73., 74., 75., 76., 77.,
#       78., 79., 80., 81., 82., 83., 84., 85., 86., 87., 88., 89., 90.,
#       91., 92., 93., 94., 95., 96., 97., 98., 99.], dtype=float32)

转变数据类型

ndarray.astype(np.float).astype

举个例子:

nd2 = np.arange(0,100,5)
nd2.dtype
#dtype('int32')
nd2.astype(np.float).dtype
#dtype('float64')
nd2.dtype
dtype('int32')

3.linspace方法创建

linspace方法也可以像arange方法很像,创建数值有规律的数组。inspace用于在指定的区间内返回间隔均匀的值。其方法如下:

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None) 
  1. start:序列的起始值。

  2. stop:序列的结束值。

  3. num:生成的样本数。默认值为50。

  4. endpoint:布尔值,如果为真,则最后一个样本包含在序列内。

  5. retstep:布尔值,如果为真,返回间距。

  6. dtype:数组的类型,默认类型为float64

    举个例子:

np.linspace(0,500,20,dtype=np.int8)
#array([   0,   26,   52,   78,  105, -125,  -99,  -72,  -46,  -20,    7,
#         33,   59,   86,  112, -118,  -91,  -65,  -39,  -12], dtype=int8)

4.ones方法创建

numpy.ones 用于快速创建数值全部为 1 的多维数组。其方法如下:

numpy.ones(shape, dtype=None, order='C')

其中:

shape:用于指定数组形状,例如(1, 2)或 3。

dtype:数据类型。

order{'C','F'},按行或列方式储存数组。

举个例子:

#主要是用来生成矩阵的 张量
#3行3列的矩阵  三维显示白的
np.ones(shape=(3,3))
#array([[1., 1., 1.],
#       [1., 1., 1.],
#       [1., 1., 1.]])

5.zeros方法创建

zeros 方法和上面的 ones 方法非常相似,不同的地方在于,这里全部填充为 0。zeros 方法和 ones 是一致的。

numpy.zeros(shape, dtype=None, order='C')

其中:

shape:用于指定数组形状,例如(1, 2)3

dtype:数据类型。

order{'C','F'},按行或列方式储存数组。

举个例子:

#零矩阵 三维显示为黑色
np.zeros(shape=(3,3)) 
#array([[0., 0., 0.],
#       [0., 0., 0.],
#       [0., 0., 0.]])

6,full方法创建

numpy.full用于创建一个自定义形状的数组,可以自己指定一个值,该值填满整个矩阵。

numpy.full(shape,fill_value=num)

举个例子:

np.full((2,3),[1,2,3])
#array([[1, 2, 3],
#       [1, 2, 3]])

7.eye 方法创建

numpy.eye 用于创建一个二维数组,其特点是k 对角线上的值为 1,其余值全部为0。方法如下:

numpy.eye(N, M=None, k=0, dtype=<type 'float'>)  
#k表示从下标第几个开始

其中:

  • N:输出数组的行数。
  • M:输出数组的列数。
  • k:对角线索引:0(默认)是指主对角线,正值是指上对角线,负值是指下对角线。

举个例子:

# 线代中的 I 表示的是单位矩阵
#单位矩阵 = 1 ,任何同行列的矩阵 * 单位矩阵 = 同行列的矩阵
I = np.eye(5,5)
I
#array([[1., 0., 0., 0., 0.],
#       [0., 1., 0., 0., 0.],
#       [0., 0., 1., 0., 0.],
#       [0., 0., 0., 1., 0.],
#       [0., 0., 0., 0., 1.]])
A = np.ndarray(shape=(5,5),dtype=np.uint8)
A
#array([[ 29,   0, 124,  10,   0],
#       [  0,   0,   0, 240, 211],
#       [ 66,   8,   0,   0,   0],
#       [  0, 208,  57, 124,  10],
#       [  0,   0,   0,   0,   8]], dtype=uint8)

8.随机数组抽样创建

(1)随机整数型矩阵

np.random.randint(low=0,high=150,size=(5,4))

  • low 表示的是最小值

  • high 表示最大值

  • size 是一个元祖类型,也可以是当单个值

  • size 是一个元祖类型,也可以是一个单个值

    举例说明:

    import random
    a = random.randint(0,100)
    b = np.random.randint(0,100,(5,4))
    a
    #89
    b
    #array([[65,  9, 40, 90],
    #       [12, 55, 34, 51],
    #       [11, 88, 63, 47],
    #       [28, 20,  5, 95],
    #       [25, 46, 13, 44]])
    

(2)标准的正太分布

np.random.randn(10,5)

没有固定的参数,每多加一个数字,代表多真假一个维度 高斯分布 每个数都在0附近

#符合大部分人的利益叫标准,不符合的就是奇特的
np.random.randn(10)
#array([ 0.73884467,  1.12546145, -0.31875133,  1.23406679, -1.21103754,
#        0.21702192,  0.73010965,  0.51373047,  0.4588801 , -0.33869427])

(3)随机抽样创建

np.random.random(size=(456,730,3))

  • size 表示形状 random随即生产的范围是0-1之间 值可以是元祖或者单个值
np.random.random(size=(5,4))
#array([[0.25779635, 0.25512994, 0.59409125, 0.54831485],
#       [0.87926247, 0.51460663, 0.62411483, 0.54362087],
#       [0.58742786, 0.69336349, 0.59884695, 0.56414724],
#       [0.45239322, 0.41447421, 0.80155812, 0.97997719],
#       [0.29203909, 0.78881759, 0.69921901, 0.57236119]])
#使用random生成图片
#405,259,3 
im = np.random.random(size=(405,259,3))
plt.imshow(im)#生成很模糊的随机图片

(4)标准方差

代表数据稳定性

np.random.normal(loc=170,scale=100,size=50)

normal也是一个正太分布的方法,生成一个一维数组

  • location 是定位的的值
  • scale 是波动值
  • size 是数据长度
#方差  标准差  求解某一组数据的稳定性
np.random.normal(loc=100,scale=100,size=20)
#array([ 80.59289487, 201.63014756,  21.02589801,  26.43460996,
#       197.49101128,  36.28011324, 284.41359354, 162.45289555,
#        83.77100481,  24.54442235,  64.85440008, 142.06517234,
#        78.50036608,  75.45910752,  -8.67749445,  34.43898874,
#        56.17053221,  83.01570787, 128.57554142, 213.71104168])

(5)随机数

每一个数据,都是一个维度

rand 和 random 的区别:random 需要 size来描述形状,而rand只需要我们直接给值,通过值的数量来确定形状

np.random.rand(d1,d2,dn)

np.random.rand(5,4)
#array([[0.33992468, 0.76175452, 0.83457972, 0.47401397],
#       [0.55375713, 0.15932915, 0.92629493, 0.81815607],
#       [0.2395769 , 0.56686094, 0.4643644 , 0.1034782 ],
#       [0.3623716 , 0.97566149, 0.08765505, 0.39677394],
#       [0.95654468, 0.83481708, 0.02188148, 0.2933859 ]])

9. linspace 与 logspace

linspace是线性生成的,是全闭区间

logspace是线性生成,并且以什么为底

start:从几开始
stop 到数字结尾
num 生成多少个数
base 表示的是底数 默认以10为底

举例:

np.logspace(1,100,10)
#array([1.e+001, 1.e+012, 1.e+023, 1.e+034, 1.e+045, 1.e+056, 1.e+067,
#       1.e+078, 1.e+089, 1.e+100])

10.diag

np.diag构建对角矩阵 np.diag(v,k=0)参数为列表即可

  • v可以是一维或二维的矩阵
  • k<0表示斜线在矩阵的下方
  • k>0表示斜线在矩阵的上方

举例:

#单位矩阵一定是对角矩阵,但是对角矩阵不一定是单位矩阵
np.diag([1,2,3,4,5,6,7])
#array([[1, 0, 0, 0, 0, 0, 0],
#       [0, 2, 0, 0, 0, 0, 0],
#       [0, 0, 3, 0, 0, 0, 0],
#       [0, 0, 0, 4, 0, 0, 0],
#       [0, 0, 0, 0, 5, 0, 0],
#       [0, 0, 0, 0, 0, 6, 0],
#       [0, 0, 0, 0, 0, 0, 7]])

11. 文件 I/O 创建数组

(1)CSV

csv,dat是一种常用的数据格式化文件类型,

读取文件数据:numpy.loadtxt('文件路径')
存储文件数据:numpy.savetxt('文件路径',数据变量)

举例:

#.dat它是一个非标准文件格式    
Matrix = np.random.randint(-np.e,np.e,size=(5,4))
Matrix
#array([[-1,  0,  0,  0],
#       [-2,  1, -2,  1],
#       [ 0, -1,  1,  0],
#       [-1, -1,  1, -2],
#       [-1, -2,  1, -2]])
np.savetxt('./M.dat',Matrix)
np.loadtxt('./M.dat')
#array([[-1.,  0.,  0.,  0.],
#       [-2.,  1., -2.,  1.],
#       [ 0., -1.,  1.,  0.],
#       [-1., -1.,  1., -2.],
#       [-1., -2.,  1., -2.]])

(2)Numpy 原生文件类型

使用 numpy.savenumpy.load 保存和读取:

A = np.random.randint(0,150,size=(5,4))
A
np.save('./A.npy',A)
np.load('./A.npy')
#array([[ 31, 130, 100,  85],
#       [134,  90, 124,  63],
#       [ 66,  58,  56,  19],
#       [134, 130,  44,   3],
#       [ 32, 124, 100,  17]])

3、ndarray数组属性

1. ndim,shape,size

  • ndim 数组的维度 (自己会计算)
  • shape 形状(5,4,3)
  • size 数组的总长度
  • dtype 查看数据类型

[[[1, 2, 3],[1, 2, 3],[1, 2, 3]],[[1, 2, 3],[1, 2, 3],[1, 2, 3]],[[1, 2, 3],[1, 2, 3],[1, 2, 3]]]

举例:

nd3 = np.array([[[1, 2, 3],[1, 2, 3],[1, 2, 3]],[[1, 2, 3],[1, 2, 3],[1, 2, 3]],[[1, 2, 3],[1, 2, 3],[1, 2, 3]]])
nd3.ndim
#3
nd3.shape
#(3, 3, 3)
nd3.size
#27
nd3.dtype
#dtype('int32')

2.ndarray.T

ndarray.T用于数组的转置(行列交换),与 .transpose() 相同。

举例:

nd4 = np.array([[1,2,3],[3,4,5]])
nd4
#array([[1, 2, 3],
#       [3, 4, 5]])
nd4.T
#array([[1, 3],
#       [2, 4],
#      [3, 5]])
#任何矩阵*自己的转置矩阵都会得到一个方阵
#2*3   3*2  = 2*2
np.dot(nd4,nd4.T)
#array([[14, 26],
#       [26, 50]])

3. ndarray.复数

coms = np.full(shape=(2,3),fill_value=1+2j)
coms
#array([[1.+2.j, 1.+2.j, 1.+2.j],
#       [1.+2.j, 1.+2.j, 1.+2.j]])

ndarray.imag 用来输出数组包含元素的虚部。

imaginary number 虚数

coms.imag
#array([[2., 2., 2.],
#       [2., 2., 2.]])

ndarray.real用来输出数组包含元素的实部。

real number 实数

#imag real 主要的作用是方便做各种波变换
coms.real
#array([[1., 1., 1.],
#       [1., 1., 1.]])

4.ndarray.itemsize

ndarray.itemsize输出一个数组元素的字节数。

one = np.ones(shape=(5,4))
#一共多少个样本,一共20个样本
one
#array([[1., 1., 1., 1.],
#       [1., 1., 1., 1.],
#       [1., 1., 1., 1.],
#       [1., 1., 1., 1.],
#       [1., 1., 1., 1.]])
one.size
#20

5. ndarray.nbytes

ndarray.nbytes用来输出数组的元素总字节数=字节数*8bit。

one.nbytes
#160   #=20*8

6. ndarray.strides

ndarray.strides用来遍历数组时,输出每个维度中步进的字节元组。

#最后一个字表示的是每一个标量占用的字节数,向前一位,4*8
one.strides
#(32, 8)#32维度字节总数  8每位的字节数

4、Numpy 数组的基本操作

1.索引

一维与列表完全一致

import numpy as np
import matplotlib.pyplot as plt
sanpang = plt.imread('./jinzhengen.png')
#ndarray对比list
li_ = [1,2,3,4,[0,1,2,[2,3,4]]]
li_
#[1, 2, 3, 4, [0, 1, 2, [2, 3, 4]]]
li_[-1][-1][-1]
#4
sanpang[0][0][0]
#0.24313726
#ndarray的索引是取决于维度的,维度越多,索引的值越多
sanpang[0,0,-1]
#0.24705882
### 2.重设形状`reshape` 可以在不改变数组数据的同时,改变数组的形状。其中,`numpy.reshape()` 等效于 `ndarray.reshape()`。`reshape`方法非常简单:

gb.shape
#(405, 259, 3)
#将三维图片变为2维图片
#改变形状的时候,样本的总个数不能少,二维的图片的是黑白,plt.imshow()方法中有额外的色素
plt.imshow(gb.reshape(405,259*3),cmap=‘gray’)
#改变形状的方法不能处理图片的灰度化


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5IGQU56E-1592462080549)(数据分析图片/重设形状1png)]```python
#reshape仅仅只能改变数组的形状
gb.reshape(405,-1)
#array([[ 67,  48,  31, ..., 156, 174, 184],
#       [ 71,  52,  35, ..., 150, 168, 178],
#       [ 77,  58,  41, ..., 145, 163, 173],
#       ...,
#       [ 83,  64,  86, ..., 128,  91, 108],
#       [ 81,  62,  84, ..., 135, 101, 117],
#       [ 84,  65,  87, ..., 141, 109, 124]], dtype=uint8)
gb.reshape((405,-1)).shape
#(405, 777)
gb.reshape(405,259*3).shape
#(405, 777)
#将上述的三维数组变成一维的数组
#-1默认将所有的维度自动相乘
gb.reshape(-1)
#array([ 67,  48,  31, ..., 141, 109, 124], dtype=uint8)

3.数组展开

ravel 的目的是将任意形状的数组扁平化,变为 1 维数组。ravel 方法如下:

不管是几维的数组都会变成1维的数据

gb.ravel()
#array([ 67,  48,  31, ..., 141, 109, 124], dtype=uint8)

4.级联

np.concatenate() 级联需要注意的点:

  1. 级联的参数是列表:一定要加中括号或小括号
  2. 维度必须相同
  3. 形状相符
  4. 【重点】级联的方向默认是shape这个tuple的第一个值所代表的维度方向
  5. 可通过axis参数改变级联的方向,默认为0, (0表示列相连,表示的X轴的事情,1表示行相连,Y轴的事情)

(1)不同列数的数组合

nd1 = np.random.randint(90,100,size=(5,4))
nd1
#array([[95, 90, 91, 99],
#       [91, 90, 93, 98],
#       [98, 96, 93, 95],
#       [98, 96, 92, 98],
#       [94, 91, 96, 97]])
nd2 = np.random.randint(0,10,size=(5,3))
nd2
#array([[1, 1, 3],
#       [3, 1, 3],
#       [5, 6, 0],
#       [7, 8, 7],
#       [3, 1, 1]])
#0叫做行方向的拼接,1是列方向上的拼接
np.concatenate((nd1,nd2),axis=1)
#array([[95, 90, 91, 99,  1,  1,  3],
#       [91, 90, 93, 98,  3,  1,  3],
#       [98, 96, 93, 95,  5,  6,  0],
#       [98, 96, 92, 98,  7,  8,  7],
#       [94, 91, 96, 97,  3,  1,  1]])

(2)不同行数的数组合并

nd1 = np.random.randint(90,100,size=(5,4))
nd1
#array([[95, 90, 91, 99],
#       [91, 90, 93, 98],
#       [98, 96, 93, 95],
#       [98, 96, 92, 98],
#       [94, 91, 96, 97]])
nd3 = np.random.randint(30,40,size=(4,4))
nd3
#array([[32, 34, 35, 38],
#       [38, 37, 39, 39],
#       [30, 34, 33, 35],
#       [36, 39, 32, 35]])
np.concatenate((nd3,nd1),axis=0)
#array([[32, 34, 35, 38],
#       [38, 37, 39, 39],
#       [30, 34, 33, 35],
#       [36, 39, 32, 35],
#       [95, 90, 91, 99],
#       [91, 90, 93, 98],
#       [98, 96, 93, 95],
#       [98, 96, 92, 98],
#       [94, 91, 96, 97]])

(3)将人和狗的图片合并

重点:图片切割为行高或者列宽相等、和图片格式的转换

sanpang = plt.imread('./jinzhengen.png')
sanpang.shape
#(273, 411, 3)
dog = plt.imread('./dog.jpg')
dog.shape
#(300, 313, 3)
#将jpg格式图片转换为png格式
dog = dog/255
dog_ = dog.copy()
#切为y轴方向点数相同:dog_[:273]
people_dog=np.concatenate((dog_[:273],sanpang),axis=1)
plt.imshow(people_dog)

图片格式转换:

#png转为jpg格式,指定数据类型
sanpang = plt.imread('./jinzhengen.png')
jpg_image=(sanpang*255).astype(np.uint8)#将jpg格式图片转换为png格式
dog = plt.imread('./dog.jpg')
png_image = dog/255

(4)堆做级联

numpy.hstack()水平|numpy.vstack()垂直

分别代表水平级联与垂直级联,填入的参数必须被小括号或中括号包裹

vertical垂直的:

horizontal水平的

stack层积

这两个函数的值也是一个list或tuple

plt.imshow(np.hstack((dog_[:273],sanpang)))

(5)分割数组

numpy.split(array,[index1,index2,…],axis)

axis默认值为0,表示垂直轴,如果值为1,表示水平的轴

注意:indices_or_sections ->[100,200]列表中有两个值,第一个值代表0:100,第二个值代表100:200,后面还有一个值200: 会产生三个值,三个值需要三个变量来接受。

例题:将人垂直切成3份

sanpang = plt.imread('./jinzhengen.png')
#序列 list  tuple
#当axis=1时候将是水平分割
k1,k2,k3,k4 = np.split(sanpang,[50,100,200],axis=0)
#jupyter 默认只打印最低端的变量
plt.imshow(k1)
plt.show()
plt.imshow(k2)
plt.show()
plt.imshow(k3)
plt.show()
plt.imshow(k4)

(6)副本

所有赋值运算不会为ndarray的任何元素创建副本。对赋值后的对象的操作也对原来的对象生效。

可使用ndarray.copy()函数创建副本(对象.copy())

fish_ = plt.imread('fish.png')
fish_Backup = fish_.copy()
#副本的作用是在开发的时候,对不了解的数据结构做一个备份,防止在后续的处理中操作失误
for i in range(10):fish_Backup[i]=0
plt.imshow(fish_Backup)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tfLVNjRX-1592462080554)(数据分析图片/覆盖png)]

plt.imshow(fish_)

5、ndarray的聚合函数

1. 求和np.sum

ndarray.sum(axis),axis不写则为所有的元素求和,为0表示行求和,1表示列求和

nd4 = np.ones(shape=(5,4))
nd4
#array([[1., 1., 1., 1.],
#       [1., 1., 1., 1.],
#       [1., 1., 1., 1.],
#       [1., 1., 1., 1.],
#       [1., 1., 1., 1.]])
nd4.sum(axis=0)#==nd4.sum(axis=-2)
#array([5., 5., 5., 5.])
np.sum(nd4,axis=1)#==np.sum(nd4,axis=-1)
#array([4., 4., 4., 4., 4.])
nd5 = np.ones(shape=(5,4,3))
nd5
#array([[[1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.]],
#
#       [[1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.]],
#
#       [[1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.]],
#
#       [[1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.]],
#
#       [[1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.]]])
nd5.sum(axis=-1)
#array([[3., 3., 3., 3.],
#       [3., 3., 3., 3.],
#       [3., 3., 3., 3.],
#       [3., 3., 3., 3.],
#       [3., 3., 3., 3.]])

求4维矩阵中最后两维的和

nd6 = np.ones(shape=(6,5,4,3))
nd6
nd6.sum(-1).sum(-1)#==nd6.sum((-1,-2))
#array([[12., 12., 12., 12., 12.],
#       [12., 12., 12., 12., 12.],
#       [12., 12., 12., 12., 12.],
#       [12., 12., 12., 12., 12.],
#       [12., 12., 12., 12., 12.],
#       [12., 12., 12., 12., 12.]])

2. 最大最小值:nd.max/ nd.min

nd7 = np.random.randint(0,100,size=(5,4))
nd7
#array([[93, 79, 65, 70],
#        [96, 35, 92, 85],
#        [25, 86, 78, 85],
#        [25, 55, 18, 28],
#        [12, 33, 54,  4]])
nd7.max()
#96
nd7.min()
#4
nd7.max(axis=0)#各列的最大值
#array([96, 86, 92, 85])
nd7.min(axis=1)#各行的最小值
#array([65, 35, 25, 18,  4])

3.平均值:nd.mean()

nd7 = np.random.randint(0,100,size=(5,4))
nd7
#array([[93, 79, 65, 70],
#        [96, 35, 92, 85],
#        [25, 86, 78, 85],
#        [25, 55, 18, 28],
#        [12, 33, 54,  4]])
nd7.mean()
#55.9
nd7.mean(axis=0)#各列的平均值
#array([50.2, 57.6, 61.4, 54.4])
nd7.mean(axis=1)#各行的平均值
#array([76.75, 77.  , 68.5 , 31.5 , 25.75])

4. 其他聚合操作

Function Name    NaN-safe Version    Description
np.sum    np.nansum    Compute sum of elements
np.prod    np.nanprod    Compute product of elements
np.mean    np.nanmean    Compute mean of elements
np.std    np.nanstd    Compute standard deviation
np.var    np.nanvar    Compute variance
np.min    np.nanmin    Find minimum value
np.max    np.nanmax    Find maximum value
np.argmin    np.nanargmin    Find index of minimum value 找到最小数的下标
np.argmax    np.nanargmax    Find index of maximum value 找到最大数的下标
np.median    np.nanmedian    Compute median of elements
np.percentile    np.nanpercentile    Compute rank-based statistics of elements
np.any    N/A    Evaluate whether any elements are true
np.all    N/A    Evaluate whether all elements are true
np.power 幂运算
np.argwhere(nd1<0)

NaN举例:

n = np.array([[1,2,3],[np.NaN,2,3]])
n
#array([[ 1.,  2.,  3.],
#       [nan,  2.,  3.]])
#任何数值+NaN返回的都是NaN
n.sum()
#nan
#带有nan的函数都会将nan视为0
np.nansum(n)
11.0

6、arg+max/min/where

(1)argmax 、argmin、 argwhere

返回的是最大值的下标,在使用argmax的时候最好把数组展开

nd9 = np.random.randint(0,150,size=(10,8))
nd9
# array([[128, 129,  12,  55, 148, 145, 127,  89],
#        [ 46, 110,  48, 114,  30,   2,   7, 139],
#        [  4, 140, 134, 127, 121, 143, 145,  30],
#        [129,  15,  95,  26,  59, 123,  68,  95],
#        [ 47,  64,  15, 144,  36,  75, 110,  21],
#        [ 29,  98,  93,  71, 108, 131,  60, 120],
#        [ 83,  34, 108,  56, 144,  16,  19,  86],
#        [141,  88,   4,  94, 132,  80,  96,   2],
#        [105,  26,  69,  82, 110,  14, 131,  97],
#        [ 89,  85, 115,  94,  55,  90,   4,  54]])
nd9.ravel()#将为一维列表
# array([128, 129,  12,  55, 148, 145, 127,  89,  46, 110,  48, 114,  30,
#          2,   7, 139,   4, 140, 134, 127, 121, 143, 145,  30, 129,  15,
#         95,  26,  59, 123,  68,  95,  47,  64,  15, 144,  36,  75, 110,
#         21,  29,  98,  93,  71, 108, 131,  60, 120,  83,  34, 108,  56,
#        144,  16,  19,  86, 141,  88,   4,  94, 132,  80,  96,   2, 105,
#         26,  69,  82, 110,  14, 131,  97,  89,  85, 115,  94,  55,  90,
#          4,  54])#找到最大值的下标,argmax在查找最大值的时候,会默认将数组扁平化
nd9.ravel()[[np.argmax(nd9.ravel())]]
#array([148])#能不写变量的地方尽量不谢,因为变量一旦定义,就需要消耗内存空间,垃圾回收需要多处理一些垃圾变量
#小于100的值
nd9.ravel()[np.argwhere(nd9.ravel()<100).ravel()]

7、轴移动

moveaxis 可以将数组的轴移动到新的位置。其方法如下:

numpy.moveaxis(a, source, destination)  

其中:

  • a:数组。
  • source:要移动的轴的原始位置。
  • destination:要移动的轴的目标位置。

举例:

nd10 = np.random.randint(0,10,size=(5,4))
nd10
# array([[0, 6, 3, 7],
#        [5, 6, 5, 8],
#        [0, 2, 5, 1],
#        [0, 8, 9, 1],
#        [9, 5, 0, 7]])
#转置
nd10.T
# array([[0, 6, 3, 7],
#        [5, 6, 5, 8],
#        [0, 2, 5, 1],
#        [0, 8, 9, 1],
#        [9, 5, 0, 7]])
nd11 = np.random.randint(0,10,size=(3,3,3))
nd11
# array([[[7, 1, 2],
#         [3, 7, 7],
#         [3, 1, 5]],#        [[0, 0, 4],
#         [0, 8, 7],
#         [9, 4, 7]],#        [[0, 2, 8],
#         [2, 3, 9],
#         [5, 2, 3]]])nd11.T
# array([[[7, 0, 0],
#         [3, 0, 2],
#         [3, 9, 5]],#        [[1, 0, 2],
#         [7, 8, 3],
#         [1, 4, 2]],#        [[2, 4, 8],
#         [7, 7, 9],
#         [5, 7, 3]]])np.moveaxis(np.moveaxis(nd11,0,-1),0,1)
# array([[[7, 0, 0],
#         [3, 0, 2],
#         [3, 9, 5]],#        [[1, 0, 2],
#         [7, 8, 3],
#         [1, 4, 2]],#        [[2, 4, 8],
#         [7, 7, 9],
#         [5, 7, 3]]])

8、轴交换

moveaxis 不同的是,swapaxes 可以用来交换数组的轴。其方法如下:

numpy.swapaxes(a, axis1, axis2) 

其中:

  • a:数组。
  • axis1:需要交换的轴 1 位置。
  • axis2:需要与轴 1 交换位置的轴 1 位置。
nd11 = np.random.randint(0,10,size=(3,3,3))
nd11
# array([[[7, 1, 2],
#         [3, 7, 7],
#         [3, 1, 5]],#        [[0, 0, 4],
#         [0, 8, 7],
#         [9, 4, 7]],#        [[0, 2, 8],
#         [2, 3, 9],
#         [5, 2, 3]]])nd11.T
#array([[[7, 0, 0],
#         [3, 0, 2],
#         [3, 9, 5]],#        [[1, 0, 2],
#         [7, 8, 3],
#         [1, 4, 2]],#        [[2, 4, 8],
#         [7, 7, 9],
#         [5, 7, 3]]])np.swapaxes(nd11,0,-1)
#array([[[7, 0, 0],
#         [3, 0, 2],
#         [3, 9, 5]],#        [[1, 0, 2],
#         [7, 8, 3],
#         [1, 4, 2]],#        [[2, 4, 8],
#         [7, 7, 9],
#         [5, 7, 3]]])

9、数组转置

transpose 类似于矩阵的转置,它可以将 2 维数组的水平轴和垂直交换。其方法如下:

numpy.transpose(a, axes=None)  

其中:

  • a:数组。
  • axis:该值默认为 none,表示转置。如果有值,那么则按照值替换轴。
nd11.transpose()
#array([[[7, 0, 0],
#         [3, 0, 2],
#         [3, 9, 5]],#        [[1, 0, 2],
#         [7, 8, 3],
#         [1, 4, 2]],#        [[2, 4, 8],
#         [7, 7, 9],
#         [5, 7, 3]]])

10、数组’循环’

数组元素的循环tilerepeat

nd13 = np.random.randint(0,10,3)
nd13
#array([6, 6, 8])
np.tile(nd13,5)
#array([6, 6, 8, 6, 6, 8, 6, 6, 8, 6, 6, 8, 6, 6, 8])
np.repeat(nd13,6)
#array([6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8])nd14 = np.random.randint(0,10,(5,4))
nd14
# array([[8, 0, 9, 3],
#        [6, 0, 5, 0],
#        [5, 2, 7, 6],
#        [6, 5, 0, 9],
#        [6, 0, 9, 2]])
np.repeat(nd14,3,axis=1)
#array([[8, 8, 8, 0, 0, 0, 9, 9, 9, 3, 3, 3],
#        [6, 6, 6, 0, 0, 0, 5, 5, 5, 0, 0, 0],
#        [5, 5, 5, 2, 2, 2, 7, 7, 7, 6, 6, 6],
#        [6, 6, 6, 5, 5, 5, 0, 0, 0, 9, 9, 9],
#        [6, 6, 6, 0, 0, 0, 9, 9, 9, 2, 2, 2]])

5、ndarray的矩阵操作

1. 基本矩阵操作

(1) 算术运算符(加减乘除):

nd15 = np.random.randint(10,100,size=(5,4))
nd16 = np.random.randint(1,10,size=(5,4))
display(nd15,nd16)
# array([[11, 75, 42, 82],
#        [24, 75, 26, 87],
#        [21, 36, 14, 88],
#        [90, 68, 37, 28],
#        [77, 25, 37, 95]])
# array([[3, 5, 1, 7],
#        [3, 1, 8, 7],
#        [9, 7, 4, 3],
#        [2, 7, 4, 4],
#        [1, 8, 5, 6]])nd15 + nd16
# array([[ 14,  80,  43,  89],
#        [ 27,  76,  34,  94],
#        [ 30,  43,  18,  91],
#        [ 92,  75,  41,  32],
#        [ 78,  33,  42, 101]])nd15 - nd16
#array([[ 8, 70, 41, 75],
#        [21, 74, 18, 80],
#        [12, 29, 10, 85],
#        [88, 61, 33, 24],
#        [76, 17, 32, 89]])nd15 * nd16
# array([[ 33, 375,  42, 574],
#        [ 72,  75, 208, 609],
#        [189, 252,  56, 264],
#        [180, 476, 148, 112],
#        [ 77, 200, 185, 570]])nd15 / nd16
#array([[ 3.66666667, 15.        , 42.        , 11.71428571],
#        [ 8.        , 75.        ,  3.25      , 12.42857143],
#        [ 2.33333333,  5.14285714,  3.5       , 29.33333333],
#        [45.        ,  9.71428571,  9.25      ,  7.        ],
#        [77.        ,  3.125     ,  7.4       , 15.83333333]])

2.np.add() 求和

不对原来的数组产生影响

np.add(nd15,nd16)
# array([[ 14,  80,  43,  89],
#        [ 27,  76,  34,  94],
#        [ 30,  43,  18,  91],
#        [ 92,  75,  41,  32],
#        [ 78,  33,  42, 101]])

3.np.multiply() 乘积

不对原来的结果产生影响,同位相乘

np.multiply(nd15,nd16)
# array([[ 33, 375,  42, 574],
#        [ 72,  75, 208, 609],
#        [189, 252,  56, 264],
#        [180, 476, 148, 112],
#        [ 77, 200, 185, 570]])

4.np.dot()矩阵的乘积

nd15 = np.random.randint(10,100,size=(5,4))
nd16 = np.random.randint(1,10,size=(5,4))
display(nd15,nd16)
# array([[94, 10, 71, 39],
#        [79, 72, 77, 38],
#        [51, 46, 87, 22],
#        [41, 29, 47, 46],
#        [19, 26, 43, 80]])
# array([[7, 5, 1, 2],
#        [1, 4, 3, 5],
#        [2, 8, 9, 2],
#        [7, 3, 1, 4],
#        [8, 3, 1, 6]])np.dot(nd15,nd16.T)
# array([[ 857,  542,  985,  915, 1087],
#        [1066,  788, 1503,  998, 1153],
#        [ 718,  606, 1297,  670,  765],
#        [ 571,  528,  829,  605,  738],
#        [ 466,  652,  793,  574,  753]])

(1)多维相乘总结:

三维乘以一维:np.dot(nd17,nd18) 降维 二维

三维乘以二维:np.dot(nd17,nd19) 还是三维

(2)广播机制

【重要】ndarray广播机制的两条规则
规则一:为缺失的维度补1
规则二:假定缺失元素用已有值填充
例1: m = np.ones((2, 3)) a = np.arange(3) 求M+a
#nd18=array([0, 3, 1])
nd18+3
#array([3, 6, 4])m = np.ones((2, 3))
a = np.arange(3)
display(m,a)
#array([[1., 1., 1.],
#       [1., 1., 1.]])
#array([0, 1, 2])
a+m
#array([[1., 2., 3.],
#       [1., 2., 3.]])

5.ndarray的排序

小测验: 使用以上所学numpy的知识,对一个ndarray对象进行选择排序。

代码越短越好

(1) 冒泡排序:

array([9, 4, 5, 7, 6, 0, 0, 3, 0, 2])

num = 0
for i in range(res.size-1):for j in range(res.size-i-1):if res[j] > res[j+1]:res[j],res[j+1] = res[j+1],res[j]num+=1
res
#array([0, 0, 0, 2, 3, 4, 5, 6, 7, 9])

(2)python+ndarray排序:

array([8, 6, 3, 1, 5, 5, 1, 2, 4, 8])

#一个循环搞定排序  argmin argmax
def sort_nd(nd):for i in range(nd.size):min_index = nd[i:].argmin()+ ind[i],nd[min_index] = nd[min_index],nd[i]
sort_nd(result)
result
#array([1, 1, 2, 3, 4, 5, 5, 6, 8, 8])

(3)快速排序

np.sort()与ndarray.sort()都可以,但有区别:

np.sort(a, axis=-1, kind='quicksort', order=None)
#kind : {'quicksort', 'mergesort', 'heapsort'}, optionalSorting algorithm. Default is 'quicksort'.
  • np.sort()不改变输入
  • ndarray.sort()本地处理,不占用空间,但改变输入
res_ = np.random.randint(0,10,size=10)
res_
#array([3, 3, 0, 3, 5, 4, 0, 2, 7, 2])
np.sort(res_)[::-1]
#array([7, 5, 4, 3, 3, 3, 2, 2, 0, 0])

(4) 部分排序

python np.partition(a,k)

有的时候我们不是对全部数据感兴趣,我们可能只对最小或最大的一部分感兴趣。

  • 当k为正时,我们想要得到最小的k个数
  • 当k为负时,我们想要得到最大的k个数
res_1 = np.random.randint(0,10000,size=100)
res_1
# array([1709, 2665, 3007, 3526, 3646,  864, 9796,  148, 8290,  505, 9249,
#        6741, 8795, 7064, 5812, 5241, 9618, 3818, 6721, 1333, 7715, 2093,
#        4247, 8537, 1161, 6773, 2475, 6879, 4275, 9834, 1403, 4711, 9187,
#        9607, 7247,  797, 8479,  149, 8054,  445, 3059, 6399, 9792, 1711,
#        4836, 4363, 7772, 7030, 1791, 6757, 2366, 5251, 6828, 5969, 7670,
#        1450, 5393, 6859, 3347, 2385, 3326, 2409, 2554, 8362, 1114, 5436,
#         399, 4108, 5116, 4582, 2345, 3580, 5788, 3676, 7640, 7906,  644,
#          62, 1050, 7893, 7372, 8485, 5739, 9402, 6608, 6070, 8869, 6203,
#        1471, 7006, 7344, 1466, 1788, 5421, 6811, 7126, 3724, 9810,  510,
#        2374])np.partition(res_1,-5)
# #array([ 148,   62,  149,  399,  445,  505,  510,  644,  797,  864, 1050,
#        1114, 1161, 1333, 1403, 1450, 1466, 1471, 1709, 1711, 1788, 1791,
#        2093, 2345, 2366, 2374, 2385, 2409, 2475, 2554, 2665, 3007, 3059,
#        3326, 3347, 3526, 3580, 3646, 3676, 3724, 3818, 4108, 4247, 4275,
#        4363, 4582, 4711, 4836, 5116, 5241, 5393, 5251, 5421, 5436, 5739,
#        5788, 5812, 5969, 6070, 6203, 6399, 6608, 6721, 6741, 6757, 6773,
#        6811, 6828, 6859, 6879, 7006, 7030, 7064, 7126, 7247, 7372, 7344,
#        7640, 7670, 7715, 7772, 7893, 7906, 8054, 8290, 8362, 8479, 8485,
#        8795, 8537, 8869, 9187, 9249, 9402, 9607, 9618, 9792, 9796, 9810,
#        9834])np.partition(res_1,4)
# array([ 148,   62,  149,  399,  445,  505,  510,  644,  797,  864, 1050,
#        1114, 1161, 1333, 1403, 1450, 1466, 1471, 1709, 1711, 1788, 1791,
#        2093, 2345, 2366, 2374, 2385, 2409, 2475, 2554, 2665, 3007, 3059,
#        3326, 3347, 3526, 3580, 3646, 3676, 3724, 3818, 4108, 4247, 4275,
#        4363, 4582, 4711, 4836, 5116, 5241, 5251, 5393, 5421, 5436, 5739,
#        5788, 5812, 5969, 6070, 6203, 6399, 6608, 6721, 6741, 6757, 6773,
#        6811, 6828, 6859, 6879, 7006, 7030, 7064, 7126, 7247, 7344, 7372,
#        7640, 7670, 7715, 7772, 7893, 7906, 8054, 8290, 8362, 8479, 8485,
#        8537, 8795, 8869, 9187, 9249, 9402, 9607, 9618, 9792, 9796, 9810,
#        9834])np.sort(res_1)[::-1][:5]
array([9834, 9810, 9796, 9792, 9618])

1.自动识别人脸

#opencv open 开源的 computer 计算机 vision视觉

import cv2
import matplotlib.pyplot as plt#plt读取图片是rgb、cv2读取图片是bgr
sanpang=cv2.imread('./jinzhengen.png')plt.imshow(sanpang[:,:,::-1])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sDb0gPyg-1592462080560)(数据分析图片/jinzhengenpng)]

#xml中封装一个算法
#CascadeClassifier分类器返回的是一个算法的shili对象
fact_det=cv2.CascadeClassifier('./haarcascade_frontalface_default.xml')#返回的是一个ndarray,第一个值表示的x轴的起始值,第二个表示y轴的起始值,第三、第四分表表示其偏移量
fact_det.detectMultiScale(sanpang)
#array([[182,  62,  61,  61]], dtype=int32)plt.imshow(sanpang[62:62+61,182:182+61][:,:,::-1])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VWstuSFm-1592462080561)(数据分析图片/人脸识别png)]

2.把图片变成圆

import os, math
from PIL import Imageg=Image.open('./guobin.jpg')
#返回一个元祖  第一个值x表示宽度  第二个值Y表示高度
g.sizedef circle(ima):#读取图片   convert转换  rgb  rgba  alpha透明度#ima = Image.open("test.jpg").convert("RGBA")#获取图片的尺寸size = ima.size# 因为是要圆形,所以需要正方形的图片   r2表示直径r2 = min(size[0], size[1])if size[0] != size[1]:ima = ima.resize((r2, r2), Image.ANTIALIAS)#创建一个画布imb = Image.new('RGBA', (r2, r2),(255,255,255,0))#读取图片数据pima = ima.load()#读取画布数据pimb = imb.load()r = float(r2/2) #圆心横坐标for i in range(r2):for j in range(r2):lx = abs(i-r+0.5) #到圆心距离的横坐标ly = abs(j-r+0.5)#到圆心距离的纵坐标l  = pow(lx,2) + pow(ly,2)if l <= pow(r, 2):pimb[i,j] = pima[i,j]imb.save("test_circle.png")plt.imshow(imb)
circle(g)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eNsj0Lbh-1592462080562)(数据分析图片/原图圆图png)]

三、pandas

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from pandas import Series,DataFrame

1、Series

Series是一种类似与一维数组的对象,由下面两个部分组成:

  • values:一组数据(ndarray类型)
  • key:相关的数据索引标签

1.Series的创建

两种创建方式:

(1) 由列表或numpy数组创建

默认索引为0到N-1的整数型索引

nd1 = np.random.randint(0,10,(5,4)).ravel()
nd1
#array([0, 0, 3, 0, 6, 2, 4, 8, 1, 2, 7, 4, 9, 3, 8, 1, 9, 9, 2, 2])

通过设置index参数指定索引

#在python中str就是object,但是object不一定是str  关联型索引
#有关联型索引的同时,也可以使用枚举型索引,也可以使用面向对象的方式取值
s1=Series(list('abcd'),index=list('东南西北'))s1['东']#s1[0]、s1.东
#'a'
s1
#东    a
#南    b
#西    c
#北    d
#dtype: object

name参数

#将当前的Series定义为数据表中的一列
s3=Series(list('abcd'),index=list('东南西北'),name='id')
s3
#东    a
#南    b
#西    c
#北    d
#dtype: object

注意:特别地,由ndarray创建的是引用,而不是副本。对Series元素的改变也会改变原来的ndarray对象中的元素。(列表没有这种情况)

(2) 由字典创建

d = {'a':1,'b':2,'c':3,'d':4}
Series(d)#强制转换
# a    1
# b    2
# c    3
# d    4
# dtype: int64

2.Series的索引和切片

可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的仍然是一个Series类型)。分为显示索引和隐式索引:

(1) 显式索引

- 使用index中的元素作为索引值
- 使用.loc[](推荐)

可以理解为pandas是ndarray的升级版,但是Series也可是dict的升级版

注意,此时是闭区间

s3=Series(list('abcd'),index=list('东南西北'))
s3
#东    a
#南    b
#西    c
#北    d
#dtype: objects3[0:2]#左开右闭
#东    a
#南    b
#Name: id, dtype: objects3['东':'西']#闭区间
# 东    a
# 南    b
# 西    c
# Name: id, dtype: object#如果索引类型是一个列表,那么可以同时取多个值
s3[['东','东','南']]
# 东    a
# 东    a
# 南    b
# Name: id, dtype: objects3.loc['东']#s3['东']、s3[0]、s3.loc[0]
#'a'

**补充查询:**查询小于50的数下标以及数值

nd1= np.random.randint(0,100,100)
cond = np.argwhere(nd1<50).ravel()#返回符合条件数据下标
nd1[cond]

(2) 隐式索引

- 使用整数作为索引值
- 使用.iloc[](推荐)

iloc[ ] 只能使用枚举型([数字:数字])的索引。

s3.iloc[0]
#'a'

(3)切片

s3.iloc[0:4] #左闭右开
# 东    a
# 南    b
# 西    c
# 北    d
# Name: id, dtype: objects3.loc['南':'北'] #全闭
# 南    b
# 西    c
# 北    d
# Name: id, dtype: object

3.Series的基本概念

可以把Series看成一个定长的有序字典

可以通过shape,ndim,size,index,values等得到series的属性。

s3=Series(list('abcd'),index=list('东南西北'))
s3.dtypes
#dtype('O')s3.size
#4s3.index
#Index(['东', '南', '西', '北'], dtype='object')s3.values
#array(['a', 'b', 'c', 'd'], dtype=object)s3.keys()
#Index(['东', '南', '西', '北'], dtype='object')

可以通过head(),tail()快速查看Series对象的样式

共同都有一个参数n,默认值为5

Series.head() DataFrame.tail()

#使用pandas读取CSV文件
k50 = pd.read_csv('./500_Cities__Local_Data_for_Better_Health.csv')

(1)head()

默认查看前五条数据,索引从零开始。

k50.head()
#   Year	StateAbbr	StateDesc	CityName	GeographicLevel	DataSource	Category	UniqueID	Measure	Data_Value_Unit	...	High_Confidence_Limit	Data_Value_Footnote_Symbol	Data_Value_Footnote	PopulationCount	GeoLocation	CategoryID	MeasureId	CityFIPS	TractFIPS	Short_Question_Text
#0	2014	US	United States	NaN	US	BRFSS	Prevention	59	Current lack of health insurance among adults ...	%	...	15.2	NaN	NaN	308745538.0	NaN	PREVENT	ACCESS2	NaN	NaN	Health Insurance
#1	2014	US	United States	NaN	US	BRFSS	Prevention	59	Current lack of health insurance among adults ...	%	...	14.3	NaN	NaN	308745538.0	NaN	PREVENT	ACCESS2	NaN	NaN	Health Insurance
#2	2014	US	United States	NaN	US	BRFSS	Health Outcomes	59	Arthritis among adults aged >=18 Years	%	...	23.7	NaN	NaN	308745538.0	NaN	HLTHOUT	ARTHRITIS	NaN	NaN	Arthritis
#3	2014	US	United States	NaN	US	BRFSS	Health Outcomes	59	Arthritis among adults aged >=18 Years	%	...	25.9	NaN	NaN	308745538.0	NaN	HLTHOUT	ARTHRITIS	NaN	NaN	Arthritis
#4	2014	US	United States	NaN	US	BRFSS	Unhealthy Behaviors	59	Binge drinking among adults aged >=18 Years	%	...	17.1	NaN	NaN	308745538.0	NaN	UNHBEH	BINGE	NaN	NaN	Binge Drinking
#5 rows × 24 columnsk50.head(n=1)#查看第一条数据
#  	Year	StateAbbr	StateDesc	CityName	GeographicLevel	DataSource	Category	UniqueID	Measure	Data_Value_Unit	...	High_Confidence_Limit	Data_Value_Footnote_Symbol	Data_Value_Footnote	PopulationCount	GeoLocation	CategoryID	MeasureId	CityFIPS	TractFIPS	Short_Question_Text
#0	2014	US	United States	NaN	US	BRFSS	Prevention	59	Current lack of health insurance among adults ...	%	...	15.2	NaN	NaN	308745538.0	NaN	PREVENT	ACCESS2	NaN	NaN	Health Insurance
#1 rows × 24 columns

(2)tail()

默认查看最后五条数据,索引从-1开始。

k50.tail()
# 	Year	StateAbbr	StateDesc	CityName	GeographicLevel	DataSource	Category	UniqueID	Measure	Data_Value_Unit	...	High_Confidence_Limit	Data_Value_Footnote_Symbol	Data_Value_Footnote	PopulationCount	GeoLocation	CategoryID	MeasureId	CityFIPS	TractFIPS	Short_Question_Text
# 810098	2014	WY	Wyoming	Cheyenne	Census Tract	BRFSS	Health Outcomes	5613900-56021001401	All teeth lost among adults aged >=65 Years	%	...	19.8	NaN	NaN	3961.0	(41.1585056144, -104.777631834)	HLTHOUT	TEETHLOST	5613900.0	5.602100e+10	Teeth Loss
# 810099	2014	WY	Wyoming	Cheyenne	Census Tract	BRFSS	Health Outcomes	5613900-56021001402	All teeth lost among adults aged >=65 Years	%	...	27.8	NaN	NaN	1913.0	(41.1717764805, -104.788212134)	HLTHOUT	TEETHLOST	5613900.0	5.602100e+10	Teeth Loss
# 810100	2014	WY	Wyoming	Cheyenne	Census Tract	BRFSS	Health Outcomes	5613900-56021001501	All teeth lost among adults aged >=65 Years	%	...	19.7	NaN	NaN	3312.0	(41.1603741708, -104.756560525)	HLTHOUT	TEETHLOST	5613900.0	5.602100e+10	Teeth Loss
# 810101	2014	WY	Wyoming	Cheyenne	Census Tract	BRFSS	Health Outcomes	5613900-56021001502	All teeth lost among adults aged >=65 Years	%	...	27.7	NaN	NaN	4518.0	(41.1506339283, -104.755675636)	HLTHOUT	TEETHLOST	5613900.0	5.602100e+10	Teeth Loss
# 810102	2014	WY	Wyoming	Cheyenne	Census Tract	BRFSS	Health Outcomes	5613900-56021002000	All teeth lost among adults aged >=65 Years	%	...	23.9	NaN	NaN	214.0	(41.1336167952, -104.719053785)	HLTHOUT	TEETHLOST	5613900.0	5.602100e+10	Teeth Loss
# 5 rows × 24 columnsk50.tail(n=1)#查看最后一条数据 
#	      Year	StateAbbr	StateDesc	CityName	GeographicLevel	DataSource	Category	UniqueID	Measure	Data_Value_Unit	...	High_Confidence_Limit	Data_Value_Footnote_Symbol	Data_Value_Footnote	PopulationCount	GeoLocation	CategoryID	MeasureId	CityFIPS	TractFIPS	Short_Question_Text
#810102	2014	WY	Wyoming	Cheyenne	Census Tract	BRFSS	Health Outcomes	5613900-56021002000	All teeth lost among adults aged >=65 Years	%	...	23.9	NaN	NaN	214.0	(41.1336167952, -104.719053785)	HLTHOUT	TEETHLOST	5613900.0	5.602100e+10	Teeth Loss
#1 rows × 24 columns

当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况,可以使用pd.isnull(),pd.notnull(),或自带isnull(),notnull()函数检测缺失数据

#NaN可以认为是MySql中的Null not null  default 
#在数据分析当中NaN也是一个不被需要的特殊数据类型
#numpy当中的NaN是float类型,当None碰到除数值类型以为的对象的时候,None不会转变成NaN
dict_ = {'a':1,'b':2,'c':None,'d':np.NaN}
s4 = Series(dict_)

(3)isnull()

c = pd.isnull(s4)
c
# a    False
# b    False
# c     True
# d     True
# dtype: bool#numpy类型序列,支持bool型,并且只返回为True的数据部分
s4[c]
# c   NaN
# d   NaN
# dtype: float64

(4)notnull()

c1 = pd.notnull(s4)
c1
# a     True
# b     True
# c    False
# d    False
# dtype: bools4[c1]
#a    1.0
#b    2.0
#dtype: float64

4.Series的运算

(1) 适用于numpy的数组运算也适用于Series

s5 = Series([1,2,3,43,57])
s5
#0     1
#1     2
#2     3
#3    43
#4    57
#dtype: int64#广播机制
s5 * 0
# 0    0
# 1    0
# 2    0
# 3    0
# 4    0
# dtype: int64s6 = Series([6,5,4,3])
s6
#s5 有5个值  s6 4个值 把位数短缺的用NaN来填补(加法类似)
s5*s6
# 0      6.0
# 1     10.0
# 2     12.0
# 3    129.0
# 4      NaN
# dtype: float64

(2) Series之间的运算

  • 在运算中自动对齐不同索引的数据
  • 如果索引不对应,则补NaN
  • 注意:要想保留所有的index,则需要使用.add()函数

nansum()

s5 = Series([1,2,3,43,57])np.nansum(s5)
#106

add()

s5.add(s6)
# 0     7.0
# 1     7.0
# 2     7.0
# 3    46.0
# 4     NaN
# dtype: float64

2、DataFrame

DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的数据集】(共用同一个行索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values(numpy的二维数组)

我们的 训练集(一些二维的数据)都是二维的,那么Series满足不了这个条件,xy轴,轴上的一点(0,0)

df = DataFrame(data={	'数学':list(range(100,105)),'语文':list(range(110,115)),'python':list(range(80,85))},index=['马云','刘强东','马化腾','雷布斯','罗太君'],columns=['数学','语文','python'])
df
# 	   数学	语文 python
# 马云 	100	110	 80
# 刘强东	101	111	81
# 马化腾	102	112	82
# 雷布斯	103	113	83
# 罗太君	104	114	84

1.DataFrame的创建

最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。

此外,DataFrame会自动加上每一行的索引(和Series一样)。

同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。

#如果数据是字典类型,那么columns只有一个排序的作用,给列排序
#列的数量可以不一致,但是行的数量必须与原数据一致,不可以增加,也不可以减少
df1 = DataFrame(data={'数学':list(range(100,105)),'语文':list(range(110,115)),'python':list(range(80,85))},index=['马云','刘强东','马化腾','雷布斯','罗太君'],columns=['python','数学','语文'])
df1
# 	 python	数学	语文
# 马云	80	100	110
# 刘强东	81	101	111
# 马化腾	82	102	112
# 雷布斯	83	103	113
# 罗太君	84	104	114

2.DataFrame属性

values、columns、index、shape、ndim、dtypes

df1.values
# array([[ 80, 100, 110],
#        [ 81, 101, 111],
#        [ 82, 102, 112],
#        [ 83, 103, 113],
#        [ 84, 104, 114]], dtype=int64)df1.columns
#Index(['python', '数学', '语文'], dtype='object')df1.index
#Index(['马云', '刘强东', '马化腾', '雷布斯', '罗太君'], dtype='object')df1.shape
#(5, 3)df1.ndim
#2df1.dtypes
#python    int64
#数学        int64
#语文        int64
#dtype: object

3.DataFrame的索引

(1) 对列进行索引

- 通过类似字典的方式
- 通过属性的方式

可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。

df1[['python','语文']]
# 	 python	语文
# 马云	80	110
# 刘强东	81	111
# 马化腾	82	112
# 雷布斯	83	113
# 罗太君	84	114df1.T['马云']
# python     80
# 数学        100
# 语文        110
# Name: 马云, dtype: int64

(2) 对行进行索引

- 使用.loc[]加index来进行行索引
- 使用.iloc[]加整数来进行行索引

同样返回一个Series,index为原来的columns。

#在dataframe中 显示索引和隐式索引默认是取行的
df1.loc['罗太君'] #关联型 
# python     84
# 数学        104
# 语文        114
# Name: 罗太君, dtype: int64#使用显示索引 查找列
df1.loc[:,'python']
# 马云     80
# 刘强东    81
# 马化腾    82
# 雷布斯    83
# 罗太君    84
# Name: python, dtype: int64#索引多行取一列
df1.loc['马云':'罗太君','python':'数学']
# 	python	数学
# 马云	80	100
# 刘强东	81	101
# 马化腾	82	102
# 雷布斯	83	103
# 罗太君	84	104df1.loc['马云','python']
#列索引和行索引都必须是枚举型
df1.iloc[0,0]
#80df1.iloc[[0,2,4],[0,-1]]
# 	python	语文
# 马云	80	110
# 马化腾	82	112
# 罗太君	84	114

4.DataFrame的运算

(1)DataFrame之间运算

同Series一样:

  • 在运算中自动对齐不同索引的数据
  • 如果索引不对应,则补NaN
#首先DataFrame是一个二维的
#在开发当中不会用df*df
np.dot(df1,df1.T)
# array([[28500, 28790, 29080, 29370, 29660],
#        [28790, 29083, 29376, 29669, 29962],
#        [29080, 29376, 29672, 29968, 30264],
#        [29370, 29669, 29968, 30267, 30566],
#        [29660, 29962, 30264, 30566, 30868]], dtype=int64)df1/0.1
#      python	数学	语文
# 马云	800.0	1000.0	1100.0
# 刘强东	810.0	1010.0	1110.0
# 马化腾	820.0	1020.0	1120.0
# 雷布斯	830.0	1030.0	1130.0
# 罗太君	840.0	1040.0	1140.0

下面是Python 操作符与pandas操作函数的对应表:

Python Operator Pandas Method(s)
+ add()
- sub(), subtract()
* mul(), multiply()
/ truediv(), div(), divide()
// floordiv()
% mod()
** pow()

(2)与Series之间运算

重要】

  • 使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。(类似于numpy中二维数组与一维数组的运算,但可能出现NaN)

  • 使用pandas操作函数:

      axis=0:以列为单位操作(参数必须是列),对所有列都有效。axis=1:以行为单位操作(参数必须是行),对所有行都有效。
    

类似矩阵相乘(行乘以列)。

(3)处理丢失的数据

#NaN就算是丢失的数据,最主要的是NaN的数据拖效率的后退 
#在Mysql中某一列含有Null的数据,那么这一列的查询速度会变慢,NUll越多越慢
df1
#  	 python	数学	语文
# 马云	80	 100 110
# 刘强东	81	101	111
# 马化腾	82	102	112
# 雷布斯	83	103	113
# 罗太君	84	104	114df1.dtypes
#python    int64
#数学        int64
#语文        int64
#dtype: objectdf1.数学.雷布斯 = np.NaN
df1
# 	python	数学	语文
# 马云	80	 100.0 110
# 刘强东	81	101.0	111
# 马化腾	82	102.0	112
# 雷布斯	83	NaN	  113
# 罗太君	84	104.0	114df1.isnull()
#      python	数学	语文
# 马云	False	False	False
# 刘强东	False	False	False
# 马化腾	False	False	False
# 雷布斯	False	True	False
# 罗太君	False	False	Falsedf1.notnull()
# 	  python	数学	语文
# 马云	True	True	True
# 刘强东	True	True	True
# 马化腾	True	True	True
# 雷布斯	True	False	True
# 罗太君	True	True	True

dropna():过滤NAN

#在开发中,如果有数据空缺,我们应当是删除行还是列?
#删除行 只有一行数据受影响了,删除列 影响了每一条数据
df1.dropna(axis=0)
# 	python	数学	语文
# 马云	80	100.0	110
# 刘强东	81	101.0	111
# 马化腾	82	102.0	112
# 罗太君	84	104.0	114

fillna() :填充数据

df1.fillna(value=0)
# 	 python	数学	语文
# 马云	80	100.0	 110
# 刘强东	81	101.0	111
# 马化腾	82	102.0	112
# 雷布斯	83	0.0	  113
# 罗太君	84	104.0	114df1.fillna(value=0)

3、pandas层次化索引

1. 创建多层行索引

(1)隐式构造

最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组

  • Series也可以创建多层索引
s = Series(data=np.random.randint(0,100,6),index=[['a','a','b','b','c','c'],['期中','期末','期中','期末','期中','期末']])
s
# a  期中    52
#    期末    28
# b  期中    27
#    期末    79
# c  期中    86
#    期末     0
# dtype: int32s['a','期中']
#52
  • DataFrame建立2级列索引
#4*6
df = DataFrame(np.random.randint(0,100,(4,6)),list('东南西北'),['python','python','ruby','ruby','golang','golang'],['期中','期末','期中','期末','期中','期末'],['甲','乙','丙','丁','戊','己']])
df
# 	python	ruby	golang
#   期中 期末	期中 期末	期中 期末
#    甲	乙	 丙	丁	  戊	 己
# 东	51	43	89	8	  20	89
# 南	42	10	35	54	30	47
# 西	1	  40	17	98	80	19
# 北	3  	21	61	49	78	36df['python','期中','甲']
#东    51
#南    42
#西     1
#北     3
#Name: (python, 期中, 甲), dtype: int32#使用隐式索引取下标,取的是最内层索引的下标值
#关联性索引只能一层一层去取(显示索引)
df.iloc[:,2]
#东    89
#南    35
#西    17
#北    61
#Name: (ruby, 期中, 丙), dtype: int32

(2) 显示构造

pd.MultiIndex

使用来创建DataFrame的多层索引

  • 使用数组
df1 = DataFrame(np.random.randint(0,150,(4,6)),list('甲乙丙丁'),pd.MultiIndex.from_arrays([['python','python','ruby','ruby','golang','golang'],['期中','期末','期中','期末','期中','期末']]))
df1
# 	python	  ruby	    golang
#   期中	期末	期中	期末	期中	期末
# 甲	57	8  	  133  	78	139	 146
# 乙	93	130	  119 	90	4	   57
# 丙	84	56	  135	 42	  136  109
# 丁	57	92	  44	 126	10	 13
  • 使用tuple
df2 = DataFrame(np.random.randint(0,150,(4,6)),list('甲乙丙丁'),pd.MultiIndex.from_tuples([('python','期中'),('python','期末'),('ruby','期中'),('ruby','期末'),('golang','期中'),('golang','期末')]))
df2
# 	python	ruby	golang
#   期中 期末 期中 期末	期中	期末
# 甲	121	110	70	 115 	51	129
# 乙	13	70	10	 136  85	92
# 丙	23	14	19	  64 125	88
# 丁	12	1	  130 	11  12	57
  • 使用product、最简单,推荐使用
df3 = DataFrame(np.random.randint(0,150,(4,6)),list('甲乙丙丁'),pd.MultiIndex.from_product([['python','ruby','golang'],['期中','期末']]))
df3
# 	python	ruby	golang
# 期中	期末	期中	期末	期中	期末
# 甲	128	67	139	89	127	116
# 乙	80	73	101	85	89	45
# 丙	75	122	61	56	141	137
# 丁	82	94	 4	13	32	11

2. 多层列+多层行索引

除了行索引index,列索引columns也能用同样的方法创建多层索引

#3层索引 行索引是8  2*2*2  列2层索引 2*5 10列
df4 = DataFrame(np.random.randint(0,150,(8,10)),pd.MultiIndex.from_product([['期中','期末'],['李斌','何小鹏'],['测试一','测试二']]),pd.MultiIndex.from_product([['上学期','下学期'],['体育','音乐','计算机','数学','语文']]))
df4
# 			上学期	                     下学期
#                 体育	音乐	计算机	数学	语文	体育	音乐	计算机	数学	语文
# 期中	李斌  测试一  39	116	36	9	132	116	104	43	107	35
# 				   测试二	95	7	54	32	122	88	44	134	85	135
# 		 何小鹏 测试一	27	14	21	132	48	90	119	79	145	107
# 					 测试二	35	79	7	40	79	144	83	148	109	18
# 期末	李斌  测试一	131	144	138	127	148	35	95	141	50	70
# 				   测试二	136	149	29	23	74	37	1	131	78	0
# 		 何小鹏 测试一	47	71	87	128	64	69	132	30	100	53
# 					 测试二	146	43	38	65	40	123	27	12	66	58

3. 多层索引与切片操作

(1)Series的操作

【重要】对于Series来说,直接中括号[]与使用.loc()完全一样,因此,推荐使用中括号索引和切片。

索引:

s = Series(data=np.random.randint(0,100,6),index=[['a','a','b','b','c','c'],['期中','期末','期中','期末','期中','期末']])
s
#a  期中    37
#   期末     9
#b  期中    40
#   期末    47
#c  期中    43
#   期末     8
#dtype: int32s.c.期末
#0s[-1]
#0

(2)DataFrame的操作

(1) 可以直接使用列名称来进行列索引

(2) 使用行索引需要用ix(),loc()等函数

【极其重要】推荐使用loc()函数

注意在对行索引的时候,若一级行索引还有多个,对二级行索引会遇到问题!也就是说,无法直接对二级索引进行索引,必须让二级索引变成一级索引后才能对其进行索引!

#3层索引 行索引是8  2*2*2  列2层索引 2*5 10列
df4 = DataFrame(np.random.randint(0,150,(8,10)),pd.MultiIndex.from_product([['期中','期末'],['李斌','何小鹏'],['测试一','测试二']]),pd.MultiIndex.from_product([['上学期','下学期'],['体育','音乐','计算机','数学','语文']]))
df4
# 			上学期	                     下学期
#                 体育	音乐	计算机	数学	语文	体育	音乐	计算机	数学	语文
# 期中	李斌  测试一  39	116	36	9	132	116	104	43	107	35
# 				   测试二	95	7	54	32	122	88	44	134	85	135
# 		 何小鹏 测试一	27	14	21	132	48	90	119	79	145	107
# 					 测试二	35	79	7	40	79	144	83	148	109	18
# 期末	李斌  测试一	131	144	138	127	148	35	95	141	50	70
# 				   测试二	136	149	29	23	74	37	1	131	78	0
# 		 何小鹏 测试一	47	71	87	128	64	69	132	30	100	53
# 					 测试二	146	43	38	65	40	123	27	12	66	58
#使用[]查找李斌 期末考试 测试二 上学期的体育成绩
df4['上学期','体育']['期末','李斌','测试二']
#136#什么时候用隐式,什么时候用显示?
#答:在搜索关键字的时候使用显示索引
#在切片的时候用隐式
df4.loc['期末','李斌','测试二']['上学期','体育']136
#136df4.iloc[5,0]
136

4. 索引的堆(stack)

  • stack() #stack()将列索引变行索引
  • unstack()

Series.stack() DataFrame.unstack()

#在pandas当中stack不是级联,而是索引的转变

df4 = DataFrame(np.random.randint(0,150,(2,2)),pd.MultiIndex.from_product([['期中'],['李斌'],['测试一','测试二']]),pd.MultiIndex.from_product([['上学期'],['体育','音乐']]))
df4# 									上学期
# 								  体育	音乐
# 期中	李斌	测试一	  20	100
# 					 测试二	104	 137

(1)stack()

【小技巧】使用stack()的时候,level等于哪一个,哪一个就消失,出现在行里。

#stack()将列索引变行索引
#-代表的是最能层的索引
df4.stack(level=0)  
#												体育	音乐
#期中	李斌	测试一	上学期	  20	100
#					 测试二	上学期	104	137#将所用的列索引变成行索引
df4.stack((-2,-1))
#期中  李斌   测试一  上学期  体育     20
#                  				音乐    100
#        		测试二  上学期  体育    104
#                  				音乐    137
#dtype: int32df4.stack().stack()
#期中  李斌  测试一  体育  上学期     20
#                  音乐  上学期    100
#          测试二   体育  上学期    104
#                  音乐  上学期    137

(2)unstack()

【小技巧】使用unstack()的时候,level等于哪一个,哪一个就消失,出现在列里。

#在查找关键字的时候非常有用,但是非常繁琐,效率又低下
df4.unstack([-1,-2,-3])#上学期  体育  测试一  期中  李斌     20
#            测试二  期中  李斌    104
#       音乐  测试一  期中  李斌    100
#            测试二  期中  李斌    137
#dtype: int32

5. 聚合操作

【注意】

  • 需要指定axis
  • 【小技巧】和unstack()相反,聚合的时候,axis等于哪一个,哪一个就保留。

所谓的聚合操作:平均数,标准差,最大值,最小值……

df4 = DataFrame(np.random.randint(0,150,(2,2)),pd.MultiIndex.from_product([['期中'],['李斌'],['测试一','测试二']]),pd.MultiIndex.from_product([['上学期'],['体育','音乐']]))
df4# 									上学期
# 								  体育	音乐
# 期中	李斌	测试一	  20	100
# 					 测试二	104	 137df4.mean(axis=1)#平均数
df4.std()#标准差
df4.max(axis=1)#最大值
df4.min(axis=0)#最小值

4、pandas的拼接操作

pandas 和 mysql 非常的相似,

mysql可以对数据进行统计

pandas主要作用就是对数据进行一个统计 pandas 也有类似于 left join 的操作 select union select

pandas的拼接分为两种:

  • 级联:pd.concat, pd.append
  • 合并:pd.merge, pd.join

0.函数生成数据:

#生成DataFrame  data   index  columns
def make_df(indexs,cols): data = {col:[str(col)+str(inds) for inds in indexs] for col in cols}return  DataFrame(data=data,index=indexs,columns=cols)

1. 使用pd.concat()级联

pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,keys=None, levels=None, names=None, verify_integrity=False,copy=True)
df1 = make_df([0,1,2],list('abc'))
df1
#  	a	  b	  c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2df2 = make_df([3,4,5],list('abc'))
df2
#  	a	  b	  c
#3	a3	b3	c3
#4	a4	b4	c4
#5	a5	b5	c5

(1) 简单级联

和np.concatenate一样,优先增加行数(默认axis=0)

pd.concat((df1,df2))
# 	a	  b	  c
# 0	a0	b0	c0
# 1	a1	b1	c1
# 2	a2	b2	c2
# 3	a3	b3	c3
# 4	a4	b4	c4
# 5	a5	b5	c5

可以通过设置axis来改变级联方向

pd.concat((df1,df2,df1),axis=1)
#   a	  b	  c	  a	  b	  c	  a	  b	  c
# 0	a0	b0	c0	NaN	NaN	NaN	a0	b0	c0
# 1	a1	b1	c1	NaN	NaN	NaN	a1	b1	c1
# 2	a2	b2	c2	NaN	NaN	NaN	a2	b2	c2
# 3	NaN	NaN	NaN	a3	b3	c3	NaN	NaN	NaN
# 4	NaN	NaN	NaN	a4	b4	c4	NaN	NaN	NaN
# 5	NaN	NaN	NaN	a5	b5	c5	NaN	NaN	NaN

注意index在级联时可以重复

r1 = pd.concat((df1,df3))
r1
# 	a	  b	  c
# 0	a0	b0	c0
# 1	a1	b1	c1
# 2	a2	b2	c2
# 1	a1	b1	c1
# 2	a2	b2	c2
# 3	a3	b3	c3r1.loc[1]
#	a	  b	  c
#1	a1	b1	c1
#1	a1	b1	c1

也可以选择忽略ignore_index,重新建立索引(也就是mysql中的id)

r2 = pd.concat((df1,df3),ignore_index=True)
r2
#   a	  b	  c
# 0	a0	b0	c0
# 1	a1	b1	c1
# 2	a2	b2	c2
# 3	a1	b1	c1
# 4	a2	b2	c2
# 5	a3	b3	c3

或者使用多层索引 keys:concat([x,y],keys=[‘x’,‘y’])

r3 = pd.concat((df1,df3),keys=['df1','df3'])
r3
# 			a		b		c
# df1	0	a0	b0	c0
# 		1	a1	b1	c1
# 		2	a2	b2	c2
# df3	1	a1	b1	c1
# 		2	a2	b2	c2
# 		3	a3	b3	c3r3.loc['df1',1]
#a    a1
#b    b1
#c    c1
#Name: (df1, 1), dtype: object

df.set_index() 设置指定的字段为行号

r4 = DataFrame(res)
r4
# 	age	city	seat	sex	sid	sname
# 0	21	上海		10	男		1	 郭斌
# 1	20	北京		2		男		2	 小京
# 2	22	北京		3		男		3	 小强
# 3	20	上海		4		男		4	 小力
# 4	21	上海		5		女		5	 小丽
# 5	42	北京		6		女		6	 小芳
# 6	65	俄国		7		男		7  普大帝
# 7	70	美利坚	100	 男	11	特朗普
# 8	70	美利坚	100  男	12	三胖
# 9	70	美利坚	100	 男	13	三胖1#在python中如果某个函数是有返回值,说明该函数不对原数据产生影响
r4.set_index('sid',inplace=True)
r4
# 	age	city seat sex	sname
# sid					
# 1	21	上海	10	男		郭斌
# 2	20	北京	2		男		小京
# 3	22	北京	3		男		小强
# 4	20	上海	4		男		小力
# 5	21	上海	5		女		小丽
# 6	42	北京	6		女		小芳
# 7	65	俄国	7		男		普大帝r4.loc[7]
# age       65
# city      俄国
# seat       7
# sex        男
# sname    普大帝
# Name: 7, dtype: object

(2) 不匹配级联

不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致

有3种连接方式:

  • 外连接:补NaN(默认模式)
pd.concat((df1,df2),axis=1,join='outer')  #outer join
# 	a		b		c		a		b		c
# 0	a0	b0	c0	NaN	NaN	NaN
# 1	a1	b1	c1	NaN	NaN	NaN
# 2	a2	b2	c2	NaN	NaN	NaN
# 3	NaN	NaN	NaN	a3	b3	c3
# 4	NaN	NaN	NaN	a4	b4	c4
# 5	NaN	NaN	NaN	a5	b5	c5
  • 内连接:只连接匹配的项
pd.concat((df1,df2),axis=1,join='inner')
#a	b	c	a	b	c
  • 连接指定轴 join_axes
df4 = make_df([0,1,2],list('cde'))
df4
#	 		c	 d	e
#0	c0	d0	e0
#1	c1	d1	e1
#2	c2	d2	e2df1
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2pd.concat((df1,df4),join='inner')
#	``c
#0	c0
#1	c1
#2	c2
#0	c0
#1	c1
#2	c2

#行和列是可以重复的、或者以谁为列属性

pd.concat((df1,df4),axis=1,join='inner')
#		a		b		c		c		d		e
#0	a0	b0	c0	c0	d0	e0
#1	a1	b1	c1	c1	d1	e1
#2	a2	b2	c2	c2	d2	e2pd.concat([df1,df4],join_axes=[df1.columns])  #轴面
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2
#0	NaN	NaN	c0
#1	NaN	NaN	c1
#2	NaN	NaN	c2

(3) drop()删除

r5 = pd.concat([df1,df4])
r5
# 	a		b		c		d		e
# 0	a0	b0	c0	NaN	NaN
# 1	a1	b1	c1	NaN	NaN
# 2	a2	b2	c2	NaN	NaN
# 0	NaN	NaN	c0	d0	e0
# 1	NaN	NaN	c1	d1	e1
# 2	NaN	NaN	c2	d2	e2r5.drop(labels='d',axis=1)#	a		b		c		e
# 0	a0	b0	c0	NaN
# 1	a1	b1	c1	NaN
# 2	a2	b2	c2	NaN
# 0	NaN	NaN	c0	e0
# 1	NaN	NaN	c1	e1
# 2	NaN	NaN	c2	e2r5.drop(labels=['d','e'],axis=1)
#		a 	b 	c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2
#0	NaN	NaN	c0
#1	NaN	NaN	c1
#2	NaN	NaN	c2

(4) insert()插入

a = r5.T
a
# 	0		1		2		0		1		2
# a	a0	a1	a2	NaN	NaN	NaN
# b	b0	b1	b2	NaN	NaN	NaN
# c	c0	c1	c2	c0	c1	c2
# g	1		2		2		3		3		4
# d	NaN	NaN	NaN	d0	d1	d2
# e	NaN	NaN	NaN	e0	e1	e2a.insert(1,3,[1,2,3,4,5,6])
a.T
# 	a		b		c		g		d		e
# 0	a0	b0	c0	1	NaN	NaN
# 3	 1	2	 	3	 	4	 5	 6
# 1	a1	b1	c1	2	NaN	NaN
# 2	a2	b2	c2	2	NaN	NaN
# 0	NaN	NaN	c0	3	d0	e0
# 1	NaN	NaN	c1	3	d1	e1
# 2	NaN	NaN	c2	4	d2	e2

(3) append()添加

df4 = make_df([0,1,2],list('cde'))
df4
#	 		c	 d	e
#0	c0	d0	e0
#1	c1	d1	e1
#2	c2	d2	e2df1
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2#outer join
df1.append(df4)
# 	a		b		c		d		e
# 0	a0	b0	c0	NaN	NaN
# 1	a1	b1	c1	NaN	NaN
# 2	a2	b2	c2	NaN	NaN
# 0	NaN	NaN	c0	d0	e0
# 1	NaN	NaN	c1	d1	e1
# 2	NaN	NaN	c2	d2	df1.T.append(df4.T,ignore_index=True)
# 	0 	1	  2
# 0	a0	a1	a2
# 1	b0	b1	b2
# 2	c0	c1	c2
# 3	c0	c1	c2
# 4	d0	d1	d2
# 5	e0	e1	e2

2. 使用pd.merge()合并

merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并

使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。

concat:一次性可以融合多张表,默认使用的全外连接
merge:一次性可以融合两张表,默认使用内连接,并且可以使用左外和右外连接,merge和mysql的sql是相似的、自动会将相同的字段合并

注意每一列元素的顺序不要求一致

(1) 一对一合并

全外连接

df1
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2df2
# 	a		b		c
#3	a3	b3	c3
#4	a4	b4	c4
#5	a5	b5	c5pd.merge(df2,df1,how='outer')
#	a		b		c
#0	a3	b3	c3
#1	a4	b4	c4
#2	a5	b5	c5
#3	a0	b0	c0
#4	a1	b1	c1
#5	a2	b2	c2

等值连接

df5
#		c		d		e
#1	c1	d1	e1
#2	c2	d2	e2
#3	c3	d3	e3df1
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2pd.merge(df1,df5) #inner
#		a		b		c		d		e
#0	a1	b1	c1	d1	e1
#1	a2	b2	c2	d2	e2

左、右外连接

df5
#		c		d		e
#1	c1	d1	e1
#2	c2	d2	e2
#3	c3	d3	e3df1
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2pd.merge(df1,df5,how='left')
#		a		b		c		d		e
#0	a0	b0	c0	NaN	NaN
#1	a1	b1	c1	d1	e1
#2	a2	b2	c2	d2	e2pd.merge(df1,df5,how='right')
#		a		b		c		d		e
#0	a1	b1	c1	d1	e1
#1	a2	b2	c2	d2	e2
#2	NaN	NaN	c3	d3	e3

(2)多对一|一对多合并

df6 = make_df([1,1,1,2,2,0],list('cde'))
display(df1,df6)
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2#		c		d		e
#1	c1	d1	e1
#1	c1	d1	e1
#1	c1	d1	e1
#2	c2	d2	e2
#2	c2	d2	e2
#0	c0	d0	e0pd.merge(df1,df6,how='right')
#	a		b		c		d		e
#0	a0	b0	c0	d0	e0
#1	a1	b1	c1	d1	e1
#2	a1	b1	c1	d1	e1
#3	a1	b1	c1	d1	e1
#4	a2	b2	c2	d2	e2
#5	a2	b2	c2	d2	e2

(3) 多对多合并

df7 = make_df([0,0,1,2,2,2],list('abc'))
display(df6,df7)
#	c		d		e
#1	c1	d1	e1
#1	c1	d1	e1
#1	c1	d1	e1
#2	c2	d2	e2
#2	c2	d2	e2
#0	c0	d0	e0#	a		b		c
#0	a0	b0	c0
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2
#2	a2	b2	c2
#2	a2	b2	c2pd.merge(df6,df7,how='left')
#		c		d		e		a		b
#0	c1	d1	e1	a1	b1
#1	c1	d1	e1	a1	b1
#2	c1	d1	e1	a1	b1
#3	c2	d2	e2	a2	b2
#4	c2	d2	e2	a2	b2
#5	c2	d2	e2	a2	b2
#6	c2	d2	e2	a2	b2
#7	c2	d2	e2	a2	b2
#8	c2	d2	e2	a2	b2
#9	c0	d0	e0	a0	b0
#10	c0	d0	e0	a0	b0

(4) key的规范化

#mysql取出来的关联表的字段大部分都不是同名字段
df4
#	c		d		e
#0	c0	d0	e0
#1	c1	d1	e1
#2	c2	d2	e2#修改字段名**
df4.columns = list('wde')
df4
#		w		d		e
#0	c0	d0	e0
#1	c1	d1	e1
#2	c2	d2	e2df1	
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2#使用on=显式指定哪一列为key,当有多个key相同时使用
pd.merge(df1,df4,on=[df1.c,df4.w])
#		a		b		c		w		d		e
#0	a0	b0	c0	c0	d0	e0
#1	a1	b1	c1	c1	d1	e1
#2	a2	b2	c2	c2	d2	e2#使用left_on和right_on指定左右两边的列作为key,当左右两边的key都不想等时使用
pd.merge(df1,df4,left_on='c',right_on='w') # on df1.c=df4.w
#		a		b		c		w		d		e
#0	a0	b0	c0	c0	d0	e0
#1	a1	b1	c1	c1	d1	e1
#2	a2	b2	c2	c2	d2	e2

(5) 内合并与外合并

  • 内合并:只保留两者都有的key(默认模式)

  • 外合并 how=‘outer’:补NaN

  • 左合并、右合并:how=‘left’,how=‘right’,

display(df1,df3)
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2#		a		b		c
#1	a1	b1	c1
#2	a2	b2	c2
#3	a3	b3	c3pd.merge(df1,df3)
#		a		b		c
#0	a1	b1	c1
#1	a2	b2	c2pd.merge(df1,df3,how='left')
#a	b	c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2pd.merge(df1,df3,how='right')
#		a		b		c
#0	a1	b1	c1
#1	a2	b2	c2
#2	a3	b3	c3#outer join = left join + righe join 所有数据
pd.merge(df1,df3,how='outer')
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2
#3	a3	b3	c3

(6) 列冲突的解决

当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名,

可以使用suffixes=自己指定后缀

#比如说mysql中有A,B表  A=[aa,bb,cc,dd] B=[cc,dd,ee,pp] cc dd数据类型是一致的,含义也一致
df8 = make_df([0,1,2],list('bcd'))
display(df1,df8)
#		a		b		c
#0	a0	b0	c0
#1	a1	b1	c1
#2	a2	b2	c2#		b		c		d
#0	b0	c0	d0
#1	b1	c1	d1
#2	b2	c2	d2pd.merge(df1,df8,left_on='b',right_on='b', suffixes=('_df1', '_df8'))
#有两个字段名完全相同的时候,merge会自动的给非指定关联的同名字段拼接一个后缀名
#两张表的中字段名一样,数据类型也一样,但是含义不一样
#		a		b	c_df1	c_df8	d               
#0	a0	b0	c0	c0	d0
#1	a1	b1	c1	c1	d1
#2	a2	b2	c2	c2	d2

3.案例分析

美国各州人口数据分析:

#               
#
#
#

5、pandas数据处理

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from pandas import Series,DataFrame

1.删除重复元素

使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True

df = DataFrame({'color':['white','pink','green','blue','white'],'size':[255,250,123,222,255]})
df
#		color	size               
#0	white	255
#1	pink	250
#2	green	123
#3	blue	222               
#4	white	255#df.duplicated() 返回bool型的值,如果不重复返回false ,有重复值返回Ture
df.duplicated(keep='first')
#0    False
#1    False
#2    False               
#3    False
#4     True
#dtype: bool#使用drop_duplicates()函数删除重复的行
#假如某一列是重复的,怎么删
df.drop_duplicates()
#		color	size
#0	white	255
#1	pink	250
#2	green	123               
#3	blue	222df1 = pd.concat((df,df),axis=1)
df1
#		color	size	color	size
#0	white	255		white	255
#1	pink	250		pink	250               
#2	green	123		green	123
#3	blue	222		blue	222
#4	white	255		white	255df1.drop_duplicates()
#		color	size	color	size               
#0	white	255		white	255
#1	pink	250		pink	250
#2	green	123		green	123
#3	blue	222		blue	222          #怎么去除重复的列
df1.T.drop_duplicates().T
#		color	size
#0	white	255
#1	pink	250
#2	green	123               
#3	blue	222
#4	white	255

2.映射

映射的含义:创建一个映射关系列表,把values元素和一个特定的标签或者字符串绑定

需要使用字典:

map = {     'label1':'value1',     'label2':'value2',...     }

包含三种操作:

  • replace()函数:替换元素
  • 最重要:map()函数:新建一列
  • rename()函数:替换索引

(1) replace()替换

使用一种数据类型dict:使用replace()函数,对values进行替换操作

df
#		color	size
#0	white	255
#1	pink	250
#2	green	123
#3	blue	222
#4	white	255dict_ = {'blue':222,'red':200}
#将默写值替换成你想要的值
df.replace(dict_)
#		color	size
#0	white	255
#1	pink	250
#2	green	123
#3	222 	222
#4	white	255

replace还经常用来替换NaN元素

df2 = DataFrame({'name':['tom',np.nan,'hanmeimei','lilei',np.nan]})
df2
#		name
#0	tom
#1	NaN
#2	hanmeimei
#3	lilei
#4	NaN#恶意字符  ?  @、fillna()只认识NaN
#用的很多,在机器学习中,
#特征工程,特征工程的步骤当中,有一步就是填充空缺值,
#np.nan, mysql中的空缺值??
ds = {'?':0,np.nan:0,'@':0}
df2.replace(ds)
#		name
#0	tom
#1	0
#2	hanmeimei
#3	lilei
#4	0

(2) map()新建列

使用map()函数,由已有的列生成一个新列

适合处理某一单独的列。

df3 = DataFrame(np.random.randint(0,150,(4,2)),list('甲乙丙丁'),['python','java'])
df3
#		python	java
#甲	2			134
#乙	74		74
#丙	69		59
#丁	54		119#我想要增加一列数学,数学的成绩是python的1.5倍
#map中的参数应当是一个函数
df3['math'] = df3['python'].map(lambda x : x * 1.5)
df3
#		python	java	math
#甲	2				134		3.0
#乙	74			74		111.0
#丙	69			59		103.5
#丁	54			119		81.0df3['python']['甲'] = np.NaN
df3['java']['乙'] = np.NaN
def con(x):if str(x) == 'nan':return 0else:return x
for k in df3.columns:df3[k]=df3[k].map(con)
df3
#		python	java		math
#甲	0.0			134.0		3.0
#乙	74.0		0.0			111.0
#丙	69.0		59.0		103.5
#丁	54.0		119.0		81.0

(3) transform()新建列

transform是变形的意思

transform中的值只能是一个function

df3
#		python java		math
#甲	0.0		134.0		3.0
#乙	74.0	0.0			111.0
#丙	69.0	59.0		103.5
#丁	54.0	119.0		81.0#将数据成绩大于60的合格,70中等,80良好,90优秀
def level(x):if x >= 90:return '优秀'elif x>=80:return '良好'elif x>=70:return '中等'elif x>=60:return '合格'else:return '养猪去吧'df3['level'] = df3['math'].transform(level)
df3
#	python	 java	 math	level
#甲	0.0		134.0	3.0	  养猪去吧
#乙	74.0	0.0		111.0	优秀
#丙	69.0	59.0	103.5	优秀
#丁	54.0	119.0	81.0	良好

(4) rename()替换索引

仍然是新建一个字典

使用rename()函数替换行索引

#行号我想要做替换
index_dict_ = {'甲':'东邪','乙':'西毒','丙':'南帝','丁':'北丐','中':'中神通'}
df3.rename(index_dict_)
#		python	java	math	level
#东邪	0.0	134.0	3.0	养猪去吧
#西毒	74.0	0.0	111.0	优秀
#南帝	69.0	59.0	103.5	优秀
#北丐	54.0	119.0	81.0	良好

3. 异常值检测和过滤

使用describe()函数查看每一列的描述性统计量

#姚明  中国男性 身高的异常值 std 标准差的数值越大 表明数据的波动就越大
df4 = DataFrame(np.random.randint(0,150,(10,4)),columns=['数学','语文','英语','物理'])
df4
#	 数学 语文 英语	物理
#0	119	66	71	44
#1	65	120	61	36
#2	27	148	93	106
#3	27	140	105	121
#4	38	149	54	125
#5	137	82	50	42
#6	16	86	80	5
#7	109	61	116	81
#8	122	80	106	132
#9	8		33	54	120df4.std()#矩阵标准差
#数学    50.021773
#语文    40.371194
#英语    24.608038
#物理    45.914897
#dtype: float64#%50表示这组数据的高斯分布中间值
#归一化  标准化
#看std就可以看出数据中是否有异常值,标准范围是有指定的
df4.describe()
#				数学				语文			英语			物理
#count	10.000000	10.000000	10.000000	10.000000
#mean		66.800000	96.500000	79.000000	81.200000
#std		50.021773	40.371194	24.608038	45.914897
#min		8.000000	33.000000	50.000000	5.000000
#25%		27.000000	69.500000	55.750000	42.500000
#50%		51.500000	84.000000	75.500000	93.500000
#75%		116.500000	135.000000	102.000000	120.750000
#max		137.000000	149.000000	116.000000	132.000000he_ = np.array([165,185])
std_ = np.array([140,122,175,175,180,181,190,195,226])
he_.std()
#10.0
std_.std()
#28.50341110190927
if std_.std() > he_.std():print('有异常值')
#有异常值

使用std()函数可以求得DataFrame对象每一列的标准差

根据每一列的标准差,对DataFrame元素进行过滤。

借助any()函数, 测试是否有True,有一个或以上返回True,反之返回False

对每一列应用筛选条件,去除标准差太大的数据

4.排序

(1)顺序排序

sort_values() sort_index()

df3.sort_values('python')
#		python java	math	level
#甲	0.0		134.0	3.0		养猪去吧
#丁	54.0	119.0	81.0	良好
#丙	69.0	59.0	103.5	优秀
#乙	74.0	0.0		111.0	优秀df3.sort_index()
#		python	java	math	level
#丁	54.0	119.0	81.0	良好
#丙	69.0	59.0	103.5	优秀
#乙	74.0	0.0		111.0	优秀
#甲	0.0		134.0	3.0		养猪去吧

(2)随机排序

使用.take()函数排序

可以借助np.random.permutation()函数随机排序

#x表示输入一个int 代表数量
#permutation+take可是做随即排序
r = np.random.permutation(4)
r
#array([1, 0, 2, 3])
df3
#		python java	 math	level
#甲	0.0		134.0	3.0		养猪去吧
#乙	74.0	0.0		111.0	优秀
#丙	69.0	59.0	103.5	优秀
#丁	54.0	119.0	81.0	良好df3.take(r)
#		python	java	math	level
#乙	74.0	0.0		111.0		优秀
#甲	0.0		134.0	3.0			养猪去吧
#丙	69.0	59.0	103.5		优秀
#丁	54.0	119.0	81.0		良好

(3)扩展:抽奖系统

#阳光普照奖  杯具
#5个人,10,20
df5 = DataFrame({'id':np.arange(0,100),'name':np.arange(1,101)})
res = np.random.permutation(100)#随机排列一个序列,或者返回一个置换的范围。
res
#array([80, 20, 83, 64, 77, 90, 48, 11, 51, 87, 53, 62, 75, 92, 32, 96, 68,
#       10, 46, 69, 24, 14, 37, 66, 26, 43, 18,  4, 60, 70, 82,  8,  9, 59,
#       78, 16, 28, 79, 15, 73, 35, 74, 84, 85, 45, 22, 55, 52, 95, 93, 98,
#        3, 47, 17, 19, 12, 36, 86, 30, 99, 57, 25, 34,  7, 63, 33, 54, 50,
#        0, 44, 21, 41,  2, 61, 23, 91, 38, 89, 58, 13, 49, 42, 56, 88, 39,
#       67, 27, 40,  1,  6, 81, 71, 65, 72, 31, 76, 94, 29, 97,  5])one = df5.take(res)[:5]
one
#		id	name
#80	80	81
#20	20	21
#83	83	84
#64	64	65
#77	77	78
two = df5.take(res)[5:15]
two
#		id	name
#90	90	91
#48	48	49
#11	11	12
#51	51	52
#87	87	88
#53	53	54
#62	62	63
#75	75	76
#92	92	93
#32	32	33

5. 数据聚合【重点】

数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。

数据分类处理:

  • 分组:先把数据分为几组
  • 用函数处理:为不同组的数据应用不同的函数以转换数据
  • 合并:把不同组得到的结果合并起来

数据分类处理的核心: groupby()函数,groupby()在pandas中也担任分组的重担

如果想使用color列索引,计算price1的均值,可以先获取到price1列,然后再调用groupby函数,用参数指定color这一列,使用.groups属性查看各行的分组情况:

df6 = DataFrame({'item':['萝卜','白菜','大蒜','洋葱','韭菜','萝卜','白菜','大蒜','洋葱','韭菜'],'seller':['赵大妈','赵大妈','李大妈','李大妈','李大妈','张大妈','张大妈','张大妈','詹大妈','詹大妈'],'price':np.random.randint(1,14,10)})
df6
#	item	seller price
#0	萝卜	赵大妈	7
#1	白菜	赵大妈	8
#2	大蒜	李大妈	13
#3	洋葱	李大妈	2
#4	韭菜	李大妈	11
#5	萝卜	张大妈	9
#6	白菜	张大妈	9
#7	大蒜	张大妈	10
#8	洋葱	詹大妈	11
#9	韭菜	詹大妈	11#groupby返回的结果是一个可迭代对象
for i in df6.groupby(['item']):print(i)
#('大蒜',   item seller  price
#2   大蒜    李大妈     13
#7   大蒜    张大妈     10)
#('洋葱',   item seller  price
#3   洋葱    李大妈      2
#8   洋葱    詹大妈     11)
#('白菜',   item seller  price
#1   白菜    赵大妈      8
#6   白菜    张大妈      9)
#('萝卜',   item seller  price
#0   萝卜    赵大妈      7 
#5   萝卜    张大妈      9)
#('韭菜',   item seller  price
#4   韭菜    李大妈     11
#9   韭菜    詹大妈     11) add_prefix()添加前缀#求各个蔬菜的平均值,并把平均的价格添加为一列 
mean_=df6.groupby(['item']).mean().add_prefix('mean_')
mean_
#		mean_price
#item	
#大蒜	11.5
#洋葱	6.5
#白菜	8.5
#萝卜	8.0
#韭菜	11.0将各个蔬菜的平均价格融合到原表当中
df7 = pd.merge(df6,mean_,left_on='item',right_index=True)
df7.sort_index()#根据行号重新排序
#		item	price	seller	mean_price
#0	萝卜	12	赵大妈		11.5
#1	白菜	8		赵大妈		4.5
#2	大蒜	5		李大妈		6.5
#3	洋葱	2		李大妈		5.0
#4	韭菜	1		李大妈		3.5
#5	萝卜	11	张大妈		11.5
#6	白菜	1		张大妈		4.5
#7	大蒜	8		张大妈		6.5
#8	洋葱	8		詹大妈		5.0
#9	韭菜	6		詹大妈		3.5#蔬菜波动 .std()
std_= df6.groupby(['item']).std().add_prefix('std_')
std_
#		std_price
#item	
#大蒜	2.121320
#洋葱	4.242641
#白菜	4.949747
#萝卜	0.707107
#韭菜	3.535534#将波动融合到原表当中
df8 = pd.merge(df7,std_,left_on='item',right_index=True)
df8
#		item	price	seller	mean_price	std_price
#0	萝卜	12	赵大妈	11.5	0.707107
#5	萝卜	11	张大妈	11.5	0.707107
#1	白菜	8		赵大妈	4.5		4.949747
#6	白菜	1		张大妈	4.5		4.949747
#2	大蒜	5		李大妈	6.5		2.121320
#7	大蒜	8		张大妈	6.5		2.121320
#3	洋葱	2		李大妈	5.0		4.242641
#8	洋葱	8		詹大妈	5.0		4.242641
#4	韭菜	1		李大妈	3.5		3.535534
#9	韭菜	6		詹大妈	3.5		3.535534

6.高级数据聚合

可以使用pd.merge()函数将聚合操作的计算结果添加到df的每一行
使用groupby分组后调用加和等函数进行运算,让后最后可以调用add_prefix(),来修改列名

可以使用transform和apply实现相同功能:在transform或者apply中传入函数即可

transform()与apply()函数还能传入一个函数或者lambda

df8
#	item	price	seller	mean_price	std_price
#0	萝卜	12	赵大妈	11.5	0.707107
#5	萝卜	11	张大妈	11.5	0.707107
#1	白菜	8		赵大妈	4.5		4.949747
#6	白菜	1		张大妈	4.5		4.949747
#2	大蒜	5		李大妈	6.5		2.121320
#7	大蒜	8		张大妈	6.5		2.121320
#3	洋葱	2		李大妈	5.0		4.242641
#8	洋葱	8		詹大妈	5.0		4.242641
#4	韭菜	1		李大妈	3.5		3.535534
#9	韭菜	6		詹大妈	3.5		3.535534#对蔬菜的价格求个和
#pandas用的不多  在mysql中用的非常的多
df8.groupby(['item'])['price'].sum()
#				item
#大蒜    23
#洋葱    13
#白菜    17
#萝卜    16
#韭菜    22
#Name: price, dtype: int32#得到的是一个Series
df8.groupby(['item'])['price'].transform(sum).drop_duplicates()
#std_0    16
#std_1    17
#std_2    23
#std_3    13
#std_4    22
#Name: price, dtype: int32#apply的操作对象,也就是传给lambda的参数是整列的数组
#sum()   np.sum()
df8.groupby(['item'])['price'].apply(np.sum)
#				item
#大蒜    13
#洋葱    10
#白菜     9
#萝卜    23
#韭菜     7
#Name: price, dtype: int64

6、pandas中绘图函数

Series和DataFrame都有一个生成各类图标的plot方法,默认情况下锁生成的都是线形图

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from pandas import Series,DataFrame

1.线形图

折线 抛物线

s = Series(np.random.randint(0,10000,10))
#plt是一个类对象
plt.plot(s)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xa0lXx4X-1592462080564)(数据分析图片/折线图png)]

#是一个Series的实例对象
#plot()函数是matplotlib的一个函数库
#为什么pandas的实例对象可以使用plot()?  因为pandas和matplotlib互相依赖,plt不引入,plot()函数将不打印图像 
s.plot()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1AntKXsI-1592462080565)(数据分析图片/折线图png)]

df = DataFrame(np.random.randint(0,10,(5,4)),columns=['python','java','golang','ruby'])
df
#			python	java	golang	ruby
#0			4			1				0				8
#1			5			5				3				5
#2			5			0				1				8
#3			0			8				2				2
#4			9			1				0				1
df.plot()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XrXFa3uZ-1592462080566)(数据分析图片/折线成绩png)]

#使用plt.plot()画出的图像是没有图例的,plt的图例需要自己去创建
plt.plot(df)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O2Xb5DNt-1592462080567)(数据分析图片/折线无图例成绩png)]

2.柱状图

DataFrame柱状图例

s1 = Series(np.random.randint(1,10,10))
s1
#0    2
#1    1
#2    8
#3    2
#4    9
#5    6
#6    1
#7    5
#8    7
#9    4
#dtype: int3
s1.plot(kind='bar')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NCv21tGO-1592462080568)(数据分析图片/柱状图png)]

df
#			python	java	golang	ruby
#0			4			1				0				8
#1			5			5				3				5
#2			5			0				1				8
#3			0			8				2				2
#4			9			1				0				1
df.plot(kind='barh')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OVFuvfXd-1592462080569)(数据分析图片/多柱形图png)]

读取tips.csv,查看每天聚会人数,每天各种聚会规模的比例 求和并df.sum(),灵活使用axis()

#是一个国外餐馆的每天人数统计,行是日期,列是人数
tips = pd.read_csv('tips.csv')
tips
#		day		1	2		3		4		5	6
#0	Fri		1	16	1		1		0	0
#1	Stat	2	53	18	13	1	0
#2	Sun		0	39	15	18	3	1
#3	Thur	1	48	4		5		1	3
#set_index()
tips.set_index('day',inplace=True)#线性图 or  直方图
tips.plot(kind='bar')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OK0g6AhW-1592462080570)(数据分析图片/营业额柱状图png)]

#1个人来 和 6个人来 数据量很小
#把数量比较小的行或列认为是不重要的,可以忽略不计的
#500W    50几块  50几块占用的比例非常的小
tips.drop(['1','6'],axis=1).plot(kind='bar')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8TSeP2cC-1592462080571)(数据分析图片/营业额修正png)]

3.直方图

random生成随机直方图,调用hist()方法

#都是做统计的,但是直方图是只认识一维的数据,而柱状图只认识二维的
S3 = Series(np.random.randint(0,10,10))
S3
#0    1
#1    1
#2    9
#3    0
#4    0
#5    5
#6    0
#7    7
#8    6
#9    6
#dtype: int32#bins表示的是图片的宽度,值越小越宽,越大越窄
S3.hist(bins=20)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AvtRjNCb-1592462080571)(数据分析图片/直方图png)]

4.饼图

【饼图也只有一个参数x!】

pie()
饼图适合展示各部分占总体的比例,条形图适合比较各部分的大小

#显示比例的
b = np.array([0.3,0.2,0.35,0.4])
plt.pie(b)
plt.axis('equal')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q71bONln-1592462080572)(数据分析图片/饼图png)]

普通未占满饼图

饼图阴影、分裂等属性设置

#labels参数设置每一块的标签;labeldistance参数设置标签距离圆心的距离(比例值)

#autopct参数设置比例值的显示格式(%1.1f%%);pctdistance参数设置比例值文字距离圆心的距离

#explode参数设置每一块顶点距圆形的长度(比例值);colors参数设置每一块的颜色;

#shadow参数为布尔值,设置是否绘制阴影

#gdp
gdp = np.array([0.2,0.8,0.5,0.3,0.15,0.4,0.05])
labels = np.array(['AnHui','JiangSu','ZheJiang','FuJian','HuNan','HeNan','SanXi'])plt.pie(gdp,labels=labels,autopct='%.2f%%',explode=[0.1,0,0.2,0,0,0,0.1])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQdIK6Wz-1592462080573)(数据分析图片/飞饼图png)]

5.散布图 散点图

df5 = DataFrame(np.random.randint(0,100,(10,3)),columns=list('ABC'))
df5
#		A		B		C
#0	61	71	98
#1	26	59	52
#2	48	31	64
#3	42	13	8
#4	48	88	6
#5	77	15	39
#6	33	22	30
#7	56	72	94
#8	6		15	43
#9	13	98	83
#在df5当中添加一个新的列,新的列叫D和C列的关系是两倍  .map()
df5['D'] = df5['C'].map(lambda x : x * 2)
df5
#		A		B		C		D
#0	61	71	98	196
#1	26	59	52	104
#2	48	31	64	128
#3	42	13	8		16
#4	48	88	6		12
#5	77	15	39	78
#6	33	22	30	60
#7	56	72	94	188
#8	6		15	43	86
#9	13	98	83	166#散点图是一个二维的图形,用x轴的坐标和y轴的坐标交汇形成
#df5是一个二维的数据,一共有4列,但是这4列对于散点图来说叫4个维度
#从df5当中抽选两列代表X和Y轴
df5.plot(kind='scatter',x='C',y='D')

6、美总统候选人政治献金

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pandas import Series,DataFrame
#月份
months = {'JAN' : 1, 'FEB' : 2, 'MAR' : 3, 'APR' : 4, 'MAY' : 5,
'JUN' : 6,'JUL' : 7, 'AUG' : 8, 'SEP' : 9, 'OCT': 10, 
'NOV': 11, 'DEC' : 12}#候选人
of_interest = ['Obama, Barack', 'Romney, Mitt', 
'Santorum, Rick', 'Paul, Ron', 'Gingrich, Newt']#党派
parties = {'Bachmann, Michelle': 'Republican','Romney, Mitt': 'Republican','Obama, Barack': 'Democrat', "Roemer, Charles E. 'Buddy' III": 'Reform','Pawlenty, Timothy': 'Republican','Johnson, Gary Earl': 'Libertarian','Paul, Ron': 'Republican','Santorum, Rick': 'Republican','Cain, Herman': 'Republican','Gingrich, Newt': 'Republican','McCotter, Thaddeus G': 'Republican','Huntsman, Jon': 'Republican','Perry, Rick': 'Republican'           }
#读取文件
ele = pd.read_csv('./usa_election.csv')
#查看文件样式以及基本信息
ele.head()#【知识点】使用map函数+字典,新建一列各个候选人所在党派party
#map()直接写字典也是可以可以使用的,传进的值会被当做是字典的键
ele['party'] = ele['cand_nm'].map(parties)
ele.head()#使用np.unique()函数查看colums:party这一列中有哪些元素
#怎么查看摸一个数值的唯一代表
ele['party'].unique()#使用value_counts()函数,统计party列中各个元素出现次数
#整张表当中都是圈钱的数据
#每个党派接受圈钱的次数
ele['party'].value_counts()  #统计关于不同党派的总记录数#【知识点】使用groupby(),查看各个党派收到的政治献金总数contb_receipt_amt
ele.groupby(['party'])['contb_receipt_amt'].sum()#查看具体每天各个党派收到的政治献金总数contb_receipt_amt
#使用groupby([多个分组参数])contb_receipt_dt
ele.groupby(['party','contb_receipt_dt'])['contb_receipt_amt'].sum()#查看日期格式,并将其转换为Pandas的日期格式,通过函数加map方式进行转换
ele.dtypes
#在mysql中时间用什么格式  datetimes  timestamp
#我现在要把contb_receipt_dt字段的格式转变为datetimes
def convert(x):#字符串分割split()day,month,year = x.split('-')mon = months[month]return '20'+year+'-'+str(mon)+'-'+day
#使用map函数
ele['contb_receipt_dt'] = ele['contb_receipt_dt'].map(convert)
ele.head()
#查看是否转换成功
ele.dtypes
#时间字段的数据格式没有转变#将时间转换为时间数据类型
#根据时间进行排序
#pd.to_datetime(某一列) 将其它类型转变为时间类型
ele['contb_receipt_dt'] = pd.to_datetime(ele['contb_receipt_dt'])
ele#得到转换后的,每天各政党所收政治献金数目。
#考察知识点:groupby(多个字段)
ele.groupby(['party','contb_receipt_dt'])['contb_receipt_amt'].sum()#【知识点】使用unstack()将上面所得数据中的party从一级索引变成列索引,
#unstack('party')
ele.unstack('party')#使用上面获取的数据
#画出各党派累计政治献金,cumsum()累加函数
#把时间作为行索引,党派作为行来观察
ele.columns
ele.set_index('contb_receipt_dt',inplace=True)
ele2 = ele.groupby(['cand_nm','contbr_occupation'])['contb_receipt_amt'].sum()
#将分布情况显示成DataFrmae
ele2.unstack
ele3 = ele2.unstack(level=0,fill_value=0)
ele3#查看老兵主要支持谁:DISABLED VETERAN
#考察Series索引
ele3.loc['DISABLED VETERAN']
#把行索引变成列,Series.reset_index()#找出各个候选人的捐赠者中,捐赠金额最大的人的职业以及捐献额
#通过query("查询条件来查找捐献人职业")
ele.columns
#找到捐赠金额最大的人   contbr_occupation
ele.groupby(['cand_nm'])['contb_receipt_amt'].max()
ele.query("cand_nm == 'Obama, Barack' & contb_receipt_amt == 1944042.43")

7、傅里叶变换变模糊

#处理音频 图片
#波 正弦波

#山峦

#符合 频域 时域 超弦

#傅里叶变换就是把 时域的东西变成频域

#傅里叶把图片变模糊,显示它的轮廓  噪音  
#007  窃听->在菜市场
import numpy as np
import matplotlib.pyplot as plt
from numpy.fft import fft,ifft#读取图片
cat = plt.imread('cat.jpg').copy()#转换为频率
cat_fft = fft(cat)#条件判断,将傅里叶数变为正数
cond = abs(cat_fft)<1e2#将其赋值为0,也就是筛选出来的值将其转变为黑色
cat_fft[cond] = 0#将傅里叶数转换回来
cat_ifft = ifft(cat_fft)#去除虚数部分
cat_ = np.real(cat_ifft)#显示图片
plt.imshow(cat_)

## 10、图片类型转换 ```python
#把PIL的图片数据和ndarray变的相同
#将PIL类型的数据转变为ndarray
moon1 = Image.open('./moonlanding.png')
#PIL图片属性
type(moon)
moon.shape
type(moon1)
moon1.tobytes()
#开始转换  变成jpg
moon1_ = np.fromstring(moon1.tobytes(),np.uint8).reshape(474,630)
#将jpg转变为png
moon1_ =  moon1_/255
moon1_
plt.figure(figsize=(18,10))
plt.imshow(moon1_,cmap='gray')#把ndarray怎么变成PIL?
#PIL格式的图片先变成二进制的,后转成图片
#把moon转变为jpg
moon_ = (moon*255).astype(np.uint8)
moon_ = moon.ravel()
moon.shape[::-1]
#要把PIL类型转变成ndarray需要shiyong numpy
#要把ndarray转成成PIL 需要使用PIL.image.frombytes()
#frombytes() 第一个参数mode指的是图片的显示方式, RGB RGBA
#第二个参数size 表达式是图片的大小 ,和ndarray表示方式相反,第一个是x轴的数字,第二个是y轴的数值
Image.frombytes(mode='RGBA',size=moon.shape[::-1],data=moon_)

四、scipy

scipy是基于numpy的

import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate  #积分呢运算模块

1、数值积分,求圆周率

#画个圆
# x^2+y^2=r^2
#y = (r^2 - x^2)^0.5
X = np.linspace(-1,1,100)  #半径是已知的条件
y = (1 - X**2)**0.5
#把图片改为正方形
plt.figure(figsize=(4,4))
plt.plot(X,y)
plt.plot(X,-y)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UU3NEEbB-1592462080586)(数据分析图片/画圆png)]

使用scipy.integrate进行积分,调用quad()方法,求圆周率

#func代表的是要进行积分求解的函数,a和b是已知数的取值范围
fx = lambda x : (1 - x**2)**0.5
#当前x不知道是多少吧,可以用a和b来定义  a=-1  b=1
pi_,basic_ = integrate.quad(fx,-1,1)
#返回的是半圆的数据,第一个值是半圆的圆周率,第二个值是计算偏差
print('计算得到的圆周率是:%s,误差是%s'%(pi_*2,basic_*2))
#计算得到的圆周率是:3.141592653589797,误差是2.000471344132393e-09

2、scripy中文件输入出

1. scipy.io

#傅里叶变换消噪获取最后的图片数据
from scipy.fftpack import fft2,ifft2
moon = plt.imread('./moonlanding.png')
moon_fft2 = fft2(moon)
cond = np.abs(moon_fft2) > 1e4
moon_fft2[cond] = 0
moon_ifft2 = ifft2(moon_fft2)
res = np.real(moon_ifft2)import scipy.io as io
#输出,也就是将数据保存  .mat数据是数据分析中常用的一种数据格式
#mdict  被保存的数据必须是一个字典类型的  res是一个ndarray类型
io.savemat('./moon_clear.mat',{'moon':res})  #输入,将数据导入进来
io.loadmat('./moon_clear.mat')['moon']

2. cv2

import cv2
cv2.imread('./moonlanding.png')
#cv2读取到的图片BGR#cv2.resize()改变图片大小
plt.imshow(cv2.resize(moon,(520,400)),cmap='gray')

3. scipy.misc

(1)图片读取、保存

#misc 各式各样,这个库种种什么样的函数都有,乱七八糟
#读写图片使用scipy中misc.imread()/imsave()
import scipy.misc as misc
#读取图片 
misc.imread('./moonlanding.png')
#保存图片
misc.imsave('./666.jpg',_6)

(2)图片旋转 、改变大小 、滤波

imrotate、imresize、imfilter 旋转 改变大小 滤波

#图片的旋转
plt.imshow(misc.imrotate(moon,60),cmap='gray')#改变图片的大小
#int 100
moon_r = misc.imresize(moon,50)
#把被压缩的数据给保存成图片
misc.imsave('moon_r.png',moon_r)
plt.imshow(moon_r,cmap='gray')
#上传图片,qq的头像,某些网站的头像,像素越高,占用的磁盘的越大,在http协议中传输的就越慢,get请求生成的缓存就越大
#头像类的图片在上传以后,一般都会在生成一个缩略图
#0.5表示压缩成原来的50%
plt.imshow(misc.imresize(moon,0.5),cmap='gray')#图片过滤
cat = plt.imread('./cat.jpg').copy()
plt.imshow(cat)
# 'blur', 'contour', 'detail', 'edge_enhance', 'edge_enhance_more',
# 模糊    轮廓     细节     边缘_增强     边缘_增强_更多
# 'emboss', 'find_edges', 'smooth', 'smooth_more', 'sharpen'.
# 浮雕     发现边缘     平滑    平滑的更多    锐化
#模糊的(也就是将上面参数填写到方法中)
plt.imshow(misc.imfilter(cat,'blur'))

3、图片处理

使用scipy.misc.face(gray=True)获取图片,

使用ndimage移动坐标、旋转图片、切割图片、缩放图片导包,读取图片显示图片

import scipy.ndimage as ndimage
face=misc.face(gray=True)
plt.imshow(face,cmap='gray')

1.shift移动坐标

#input 表示的是数组
#shift 表示的是移动坐标的值,黑白图片是二维的,只有两个值
#'constant', 'nearest', 'reflect', 'mirror' or 'wrap'
# 平常的      相近的     反射       镜子        包裹
plt.imshow(ndimage.shift(face,[100,0],mode='nearest'),cmap='gray')#彩图(重点注意三维规律)
face_ = misc.face()
plt.imshow(face_)
#移动坐标
plt.imshow(ndimage.shift(face_,[768,1024,4],mode='mirror'))

2.zoom缩放图片

#misc.imresize 50
#如果是一个int,那就将图片放大几倍
#(0.5,0.8) 将y压缩50%  将x压缩80%
#misc.imresize()  cv2.resize()
plt.imshow(ndimage.zoom(face,(0.5,0.5)),cmap='gray')#zoom进行压缩彩图
#不管压缩什么维度,只要图片颜色都不能压缩,参数写1,表示不变
plt.imshow(ndimage.zoom(face_,(0.5,0.5,1)))

3.图片进行过滤

(1)高斯滤波

gaussian_filter

np.random.randn(face.shape[0],face.shape[1]) * face.std()
#给face中添加一些噪点
face_blur = face + np.random.randn(face.shape[0],face.shape[1]) * face.std()
plt.imshow(face_blur,cmap='gray')#使用高斯滤波进行过滤
#同时打印三张图片  原图片  模糊以后的图片   打印高斯滤波过滤的图片
#先定义图片的尺寸
plt.figure(figsize=(18,12))
#subplot()   第一个值代表几行  第二个值代表几列 第三个值代表图片的编号,默认从1开始,每张图片的编号不能重复#显示原图片
axes = plt.subplot(1,3,1)
axes.imshow(face,cmap='gray')#显示噪点处理图片
axes = plt.subplot(132)
axes.imshow(face_blur,cmap='gray')#高斯滤波过滤以后的图片
axes = plt.subplot(133)
axes.imshow(ndimage.gaussian_filter(face_blur,1),cmap='gray')

(2)中值滤波

中值滤波参数size:给出在每个元素上从输入数组中取出的形状位置,定义过滤器功能的输入:median_filter

#使用高斯滤波进行过滤
#同时打印三张图片  原图片  模糊以后的图片   打印高斯滤波过滤的图片
#先定义图片的尺寸
plt.figure(figsize=(18,12))
#subplot()   第一个值代表几行  第二个值代表几列 第三个值代表图片的编号,默认从1开始,每张图片的编号不能重复
axes = plt.subplot(1,3,1)
axes.imshow(face,cmap='gray')axes = plt.subplot(132)
axes.imshow(face_blur,cmap='gray')axes = plt.subplot(133)
#中值滤波过滤以后的图片
#size是过滤选择的像素个数
axes.imshow(ndimage.median_filter(face_blur,size=4),cmap='gray')

(3)signal维纳滤波

signal维纳滤波mysize:滤镜尺寸的标量

import scipy.signal as signalplt.figure(figsize=(18,12))# subplot第一参数的第一个值 代表几行 第二个值代表几列
# 第三个值代表图片的编号 默认从1开始 每张图片的编号不能重复
axes = plt.subplot(1,3,1)
axes.imshow(face,cmap='gray')axes = plt.subplot(1,3,2)
axes.imshow(face_blur,cmap='gray')axes = plt.subplot(1,3,3)
axes.imshow(signal.wiener(face_blur,5),cmap='gray')

(4)登月高斯滤波

moon=plt.imread('./moonlanding.png')
moon_gaus = ndimage.gaussian_filter(moon,2)
plt.figure(figsize=(12,9))
plt.imshow(moon_gaus,cmap='gray')

(5)高斯模糊(半)

import PIL.Image as Image
import PIL.ImageFilter as ImageFilter
plt.imshow(cat)
_1,_2 = np.split(cat,[int(cat.shape[1]/2)],axis=1)
#data应当是一维数据
#PIL.Image.Image的shape是与ndarray的shape的长宽相反
_2.shape[::-1]
cat_r = Image.frombytes(mode='RGB',size=(365,456),data=_2.ravel())
#开始高斯模糊
cat_r_blur = cat_r.filter(ImageFilter.GaussianBlur(radius=10))
#转换成ndarray类型
_res = np.fromstring(cat_r_blur.tobytes(),np.uint8).reshape(_2.shape)
#将左右两张图片进行级联
result = np.concatenate([_1,_res],axis=1)
result.shape
#显示(可做保存)
plt.imshow(result)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vZyqO3hS-1592462080588)(数据分析图片/高斯半模糊 png)]

(6)高斯模糊(全)

import PIL.Image as Image
import PIL.ImageFilter as ImageFilter
#高斯模糊只能处理PIL类型的数据
c = Image.open('./cat.jpg')
type(c)
c.filter(ImageFilter.GaussianBlur(radius=10))

五、Matplotlib

数据分析第7天的学习内容(主要画图)

- 一、【重点】Matplotlib基础知识
- 二、设置plot的风格和样式- 1、【重点】点和线的样式- 2、X、Y轴坐标刻度
- 三、2D图形- 1、示例- 2、【重点】直方图- 3、【重点】条形图- 4、【重点】饼图- 5、【重点】散点图
=============以上为重点=================
以下自学
- 四、图形内的文字、注释、箭头- 1、图形内的文字- 2、注释- 3、箭头
- 五、3D图- 1、曲面图

Matplotlib中的基本图表包括的元素

  • x轴和y轴
    水平和垂直的轴线

  • x轴和y轴刻度
    刻度标示坐标轴的分隔,包括最小刻度和最大刻度

  • x轴和y轴刻度标签
    表示特定坐标轴的值

  • 绘图区域
    实际绘图的区域

import numpy as np
import matplotlib.pyplot as plt

1、数据图的参数

1.只含单一曲线的图

#线性图是二维,x轴和y轴
#正弦波
x = np.linspace(-5,5,100)
y = np.sin(x)
plt.plot(x,y)

2.包含多个曲线的图

1、可以使用多个plot函数(推荐),在一个图中绘制多个曲线

x = np.linspace(-5,5,100)
y = np.sin(x)
y2 = np.cos(x)
plt.plot(x,y)
plt.plot(x,y2)#如果在一个plot中画多条曲线,那么数据必须成对出现
plt.plot(x,y,x,y2)

3.网格线

x = np.linspace(-5,5,100)
y = np.sin(x)
y2 = np.cos(x)
plt.plot(x,y,x,y2)
plt.grid()

设置grid参数(参数与plot函数相同),使用plt面向对象的方法,创建多个子图显示不同网格线
lw代表linewidth,线的粗细
alpha表示线的明暗程度
color代表颜色

#绘制三张图
#第一张图 是xy都有网格线  第二张图 x轴有网格线  第三张图  y轴有网格线
plt.figure(figsize=(3*4,4)) axes= plt.subplot(1,3,1)
axes.plot(x,y)
axes.grid(color='pink')#x走的网格线在横向柱状图的时候经常用到
axes= plt.subplot(132)
axes.plot(x,y)
axes.grid(color='orange',linestyle='--',axis='x')#y轴的网格线在画柱状图的时候很有效果
axes= plt.subplot(133)
axes.plot(x,y)
axes.grid(color='green',ls='-.',axis='y')

4.坐标轴界限

plt.axis() 修改界限

plt.plot(x,y,x,y2)
#plt.axis('off')  #取消刻度
#plt.axis([-5,5,-2,3]) #自定义刻度轴,值是一个序列类型的,数值必须要成对出现
#plt.axis('equal')  #画员的时候很有用
#plt.axis('image') #压缩图片,将空白区域全部取出
#plt.axis('scaled')  #压缩图片,将空白区域全部取出
#plt.axis('normal')  #标准的
plt.axis('auto')    #自动的#圆形
X = np.linspace(-1,1,100)
f = lambda x : (1 - X**2)**0.5
plt.plot(X,f(X),X,-f(X))
plt.axis('equal')

5.刻度轴的标题设置

plt.xlabel() plt.ylabel()

X = np.linspace(-1,1,100)
f = lambda x : (1 - X**2)**0.5
plt.plot(X,f(X),X,-f(X))
plt.axis('equal')
#自定义x和y走的刻度
plt.xlim([-3,2])
plt.ylim([-3,2])#给可独奏设置标题
plt.xlabel('X',fontsize=30,color='red')
#rotation 旋转 值是整数型 代表旋转多少角度
plt.ylabel('f(X) = (1-X^2)^0.5',fontsize=20,color='orange',rotation=90)

plt.xlim() plt.ylim()

6.标题的设置

title() set_title()

X = np.linspace(-1,1,100)
f = lambda x : (1 - X**2)**0.5
plt.plot(X,f(X),X,-f(X))
plt.axis('equal')
#自定义x和y走的刻度
plt.xlim([-3,2])
plt.ylim([-3,2])#给可独奏设置标题
plt.xlabel('X',fontsize=30,color='red')
#rotation 旋转 值是整数型 代表旋转多少角度
plt.ylabel('f(X) = (1-X^2)^0.5',fontsize=20,color='orange',rotation=90)
#设置图片的标题
plt.title('this is circle',fontsize=40,color='cyan',rotation=10)

7.图例

两种传参方法:

【推荐使用】在plot函数中增加abel参数
在legend方法中传入字符串列表

x = np.linspace(-np.pi,np.e,100)
y = np.sin(x)
y2 = np.cos(x)
plt.plot(x,y,x,y2)
#legend 传入的值是一个列表 ,列表中第一个值是x轴的图例,第二个值是y轴的图例
plt.legend(['sin(x)','cos(x)'])

(1)label属性

label是plot()的属性,label是标签的意思,在plt中代表图例的名称

定义label以后,不调用legend()图例依然不会显示

plt.plot(x,y,label='sin(x)')
plt.plot(x,y2,label='cos(x)')
plt.legend(loc=0)

plot中,label的值前面加上一个下划线就不显示,表示隐藏

plt.plot(x,y2,_label='cos(x)')

loc参数:

loc 是控制图例的位置的

best 是最好的位置

default :upper right 右上角

字符串 数值 字符串 数值
best 0 center left 6
upper right 1 center right 7
upper left 2 lower center 8
lower left 3 upper center 9
lower right 4 center 10
right 5

loc参数可以是序列类型,表示图例左下角的坐标:

plt.legend(loc=[0.4,1])loc 序列中写int类型对应的是图片的尺寸比例

ncol参数:

plt.legend(loc=[0,1],ncol=4)loc 序列中写int类型对应的是图片的尺寸比例,ncol表示一列几个图例

8.保存图片

figure.savefig的选项

  • filename
    含有文件路径的字符串或Python的文件型对象。图像格式由文件扩展名推断得出,例如,.pdf推断出PDF,.png推断出PNG (“png”、“pdf”、“svg”、“ps”、“eps”……)
  • dpi
    图像分辨率(每英寸点数),默认为100
  • facecolor
    图像的背景色,默认为“w”(白色)
x = np.linspace(-4,4,100)
y = np.sin(x)
y2 = np.cos(x)
#画三条线
plt.plot(x,y,label='sin(x)',linestyle='-.',color='pink')
plt.plot(x,y2,label='cos(x)',linestyle=':',color='#FF0000',linewidth=10)
plt.plot(x,y*2+y2/2,label='complex',marker='o')
plt.legend()#保存图片
plt.savefig('./fig.png',dpi=100,facecolor='orange')

2、设置plot的风格和样式

1.颜色

参数color或c,图形中线段颜色

plt.plot(x,y,color='r',c='c')
#全字母参数的优先级更加高

色值的方式:

  • 别名

    • color=‘r’
  • 合法的HTML颜色名

    • color = ‘red’
颜色 别名 HTML颜色名 颜色 别名 HTML颜色名
蓝色 b blue 绿色 g green
红色 r red 黄色 y yellow
青色 c cyan 黑色 k black
洋红色 m magenta 白色 w white
  • HTML十六进制字符串

    • color = '#eeefff ’ #若是#eeefff99 其中99代表百分制透明度
  • 归一化到[0, 1]的RGB元组

    • color = (0.3, 0.3, 0.4)

2.透明度

alpha参数

plt.plot(x,y,color='cyan',alpha=0.1)
#其中的最后的0.5指的是透明度 
plt.plot(x,y,color=(0.0001,0.9999,0.5555,0.5))

3.背景色

设置背景色,通过plt.subplot()方法传入facecolor参数,来设置坐标轴的背景色

#subplot()是画布的对象
axes=plt.subplot(facecolor='k')
axes.plot(x,y,color=(0.0001,0.9999,0.5555),linewidth=50)

4.线型

参数linestyle或ls

线条风格 描述 线条风格 描述
‘-’ 实线 ‘:’ 虚线
‘–’ 破折线 ‘steps’ 阶梯线
‘-.’ 点划线 ‘None’ / ‘,’ 什么都不画
x = np.linspace(-np.e,np.e,10)
y = np.sin(x)
y2 = np.cos(x)
axes=plt.subplot(facecolor='k')
axes.plot(x,y2,color=(0.0001,0.9999,0.5555),linewidth=10,ls=':')

5.线宽

linewidth或lw参数

axes=plt.subplot(facecolor='k')
axes.plot(x,y2,color=(0.0001,0.9999,0.5555),lw=5,ls='steps')

6.不同宽度的破折线

axes=plt.subplot(facecolor='k')
axes.plot(x,y2,color=(0.0001,0.9999,0.5555),linewidth=2,ls='-.',dashes=[10,5,2,8])
#dashes将虚线线段范围四段,比例是10:5:2:8

7.点型

marker参数

标记 描述 标记 描述
‘1’ 一角朝下的三脚架 ‘3’ 一角朝左的三脚架
‘2’ 一角朝上的三脚架 ‘4’ 一角朝右的三脚架
plt.figure(figsize=(12,6))
x = np.linspace(-np.pi,np.pi,100)
y = np.sin(x)
axes=plt.subplot(facecolor='k')
#markersize
axes.plot(x,y,color=(0.0001,0.9999,0.5555),marker=1,markersize=150)
标记 描述 标记 描述
‘s’ 正方形 ‘p’ 五边形
‘h’ 六边形1 ‘H’ 六边形2
‘8’ 八边形
plt.figure(figsize=(12,6))
x = np.linspace(-np.pi,np.pi,7)
y = np.sin(x)
axes=plt.subplot(facecolor='k')
#markersize
axes.plot(x,y,color=(0.0001,0.9999,0.5555),marker='8')
标记 描述 标记 描述
‘.’ ‘x’ X
‘*’ 星号 ‘+’ 加号
‘,’ 像素
plt.figure(figsize=(12,6))
x = np.linspace(-np.pi,np.pi,7)
y = np.sin(x)
axis = plt.subplot(facecolor='k')
axis.plot(x,y,color=(0.0001,0.9999,0.5555),marker='*',markersize=20)
标记 描述 标记 描述
‘o’ 圆圈 ‘D’ 菱形
‘d’ 小菱形 ‘’,‘None’,’ ',None
plt.figure(figsize=(12,6))
x = np.linspace(-np.pi,np.pi,7)
y = np.sin(x)
axis = plt.subplot(facecolor='k')
axis.plot(x,y,color=(0.0001,0.9999,0.5555),marker='d',markersize=20)
标记 描述 标记 描述
‘_’ 水平线 ‘|’ 垂直线
plt.figure(figsize=(12,6))
x = np.linspace(-np.pi,np.pi,7)
y = np.sin(x)
axis = plt.subplot(facecolor='k')
axis.plot(x,y,color=(0.0001,0.9999,0.5555),marker='|',markersize=20)

标记 描述 标记 描述 ‘v’ 一角朝下的三角形 ‘<’ 一角朝左的三角形 ‘^’ 一角朝上的三角形 ‘>’ 一角朝右的三角形

8.多参数连用

颜色、点型、线型

x = np.linspace(-4,4,10)
y = np.sin(x)
y2 = np.cos(x)plt.plot(x,y,'cD--',x,y2,'ko:')

9.更多点和线的设置

参数 描述 参数 描述
color或c 线的颜色 linestyle或ls 线型
linewidth或lw 线宽 marker 点型
markeredgecolor 点边缘的颜色 markeredgewidth 点边缘的宽度
markerfacecolor 点内部的颜色 markersize 点的大小
x = np.linspace(0,10,10)
y = x
plt.plot(x,y,c='r',ls='--',marker='o',markersize=10,markeredgecolor='g',markeredgewidth=3)
plt.savefig('line.png',dpi=100)

10.一条为多个曲线设置

(1)多曲线统一样式

属性名声明

plt.plot(x1, y1, x2, y2, fmt, …)

x = np.linspace(-5,5,100)
y = np.sin(x)
y2 = np.cos(x)plt.plot(x,y,x,y2,c='r',ls='--')

(2)多个曲线不同设置

多个都进行设置时,无需声明属性 plt.plot(x1, y1, fmt1, x2, y2, fmt2, …)

plt.plot(x,y,'b+--',x,y2,'ro:')

(3)对实例使用样式的set方法

line1,line2 = plt.plot(x,y,x,y2)line1.set_color('r')
line1.set_linestyle('--')
line1.set_marker('D')

或者:使用plt.setp()方法

line1,line2 = plt.plot(x,y,x,y2)plt.setp(line1,c='r',ls='--',marker='d')

11.X、Y轴坐标刻度

xticks()和yticks()方法

x = np.arange(10)
y = np.sin(x)plt.plot(x,y)
#xticks 第一个参数,代表是我们刻度轴的原来的数字,第二个参数是需要做映射的字符列表
plt.xticks(np.arange(10),list('abcdefghij'),fontsize=20,color='r',rotation=60)
#正弦波 min 0 max
plt.yticks([-1,0,1],['min',0,'max'],size=20,color='orange',rotation=30)
plt.savefig('sin(x).pdf')

面向对象方法

set_xticks、set_yticks、set_xticklabels、set_yticklabels方法

#刻度是不是线条可以控制的范围
axes = plt.subplot()line = plt.plot(x,y)
plt.setp(line,c='r')axes.set_xticks(np.arange(10))
axes.set_xticklabels(list('abcdefghij'),color='green',size=20,rotation=20)

12.正弦余弦(π)

LaTex语法,用ππ等表达式在图表上写上希腊字母

x = np.linspace(-np.pi,np.pi,100)
y = np.sin(x)
y2 = np.cos(x)
axes = plt.subplot()
plt.plot(x,y,x,y2)
pi = np.pi
axes.set_xticks([-pi,-pi/2,0,pi/2,pi])
#plt的实体标签    $\pi$
axes.set_xticklabels(['-$\pi$','-$\pi$/2',0,'$\pi$/2','$\pi$'],size=20)

六、K-近邻算法(KNN)

众所周知,电影可以按照题材分类,然而题材本身是如何定义的?由谁来判定某部电影属于哪 个题材?也就是说同一题材的电影具有哪些公共特征?这些都是在进行电影分类时必须要考虑的问 题。没有哪个电影人会说自己制作的电影和以前的某部电影类似,但我们确实知道每部电影在风格 上的确有可能会和同题材的电影相近。那么动作片具有哪些共有特征,使得动作片之间非常类似, 而与爱情片存在着明显的差别呢?动作片中也会存在接吻镜头,爱情片中也会存在打斗场景,我们 不能单纯依靠是否存在打斗或者亲吻来判断影片的类型。但是爱情片中的亲吻镜头更多,动作片中 的打斗场景也更频繁,基于此类场景在某部电影中出现的次数可以用来进行电影分类。

1、k-近邻算法原理

简单地说,K-近邻算法采用测量不同特征值之间的距离方法进行分类。

  • 优点:精度高、对异常值不敏感、无数据输入假定。
  • 缺点:时间复杂度高、空间复杂度高。
  • 适用数据范围:数值型和标称型。

2、工作原理

存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据
与所属分类的对应关系。输人没有标签的新数据后,将新数据的每个特征与样本集中数据对应的
特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们
只选择样本数据集中前K个最相似的数据,这就是K-近邻算法中K的出处,通常*K是不大于20的整数。
最后 ,选择K个最相似数据中出现次数最多的分类,作为新数据的分类*。knn = KNeighborsClassifier()  #将knn算法实例化
knn.fit(X_train,y_train)  #将数据训练,返回的是算法的模型
y_ = knn.predict(X_test)#进行数据的预测
knn.score(X_train,y_train)#模型的评估,对于分类算法来说,就是给模型打分
knn.score(X_test,y_test)#给测评结果打分

3、简单代码实现

import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import matplotlib.pyplot as pltmoive = pd.read_excel('./tests.xlsx',sheet_name=1)
moive
电影名称 武打镜头 接吻镜头 分类情况
0 大话西游 36 1 动作片
1 杀破狼 43 2 动作片
2 前任3 0 10 爱情片
3 战狼2 59 1 动作片
4 泰坦尼克号 1 15 爱情片
5 星语心愿 2 19 爱情片
#1.数据的预处理
#X_train这个变量在机器学习中代表训练数据,特征数据是二维的
X_train = moive.iloc[:,1:-1]
#y_train代表的是训练数据的目标值,目标值都是一维的
y_train = moive['分类情况']
display(X_train,y_train)
武打镜头 接吻镜头
0 36 1
1 43 2
2 0 10
3 59 1
4 1 15
5 2 19
#0    动作片
#1    动作片
#2    爱情片
#3    动作片
#4    爱情片
#5    爱情片
#Name: 分类情况, dtype: object
#2.模型的建立
from sklearn.neighbors import KNeighborsClassifier  #分类器
#n_neighbors=5  默认计算最近的五个数据,属于哪一类最多,它就是哪一类
knn = KNeighborsClassifier()  #将knn算法实例化
#对数据进行训练
knn.fit(X_train,y_train)  #将数据训练,返回的是算法的模型#3.对模型进行评估和预测
#首先我们需要数据集,我们自己先创建数据集
new_moive = DataFrame(np.array([['千星之城',50,10],['邪不压正',30,2],['僵尸先生',100,2],['咒怨',0,0]]),columns=['电影名称','武打镜头','接吻镜头'])
new_moive  #预测数据X_test = new_moive.iloc[:,1:]
X_test
#进行数据的预测
y_ = knn.predict(X_test)
y_#显示预测结果 array(['动作片', '动作片', '动作片', '爱情片'], dtype=object)#模型的评估,对于分类算法来说,就是给模型打分
knn.score(X_train,y_train)
#给预测数据定义目标值
y_test=np.array(['动作片', '动作片', '动作片', '惊悚片'])
#为什么评估的时候要打分两次?
#给训练数据可以观测到数据的拟合性,给预测数据打分可以得到当前模型的泛化性
knn.score(X_test,y_test)

4、人体动作识别

练习 人类动作识别 步行,上楼,下楼,坐着,站立和躺着

人类动作识别
步行,上楼,下楼,坐着,站立和躺着

数据采集每个人在腰部穿着智能手机,进行了六个活动(步行,上楼,下楼,坐着,站立和躺着)。采用嵌入式加速度计和陀螺仪,以50Hz的恒定速度捕获3轴线性加速度和3轴(3维空间的XYZ轴)角速度(时间转一圈多少时间),来获取数据

import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import matplotlib.pyplot as pltlabel = {1:'walking',2:'upstairs',3:'downstairs',4:'siting',5:'standing',6:'lying'}

我们导入几个包x_test.npy x_train.npy y_test.npy y_train.npy ,这些都是numpy保存的数据

#导入数据集
X_train = np.load('./knn_test/x_train.npy')
y_train = np.load('./knn_test/y_train.npy')
X_test  = np.load('./knn_test/x_test.npy')
y_test  = np.load('./knn_test/y_test.npy')#分类  频率
knn = KNeighborsClassifier()
knn.fit(X_train,y_train)#测试
y_ = knn.predict(X_test)
y_#评分
knn.score(X_train,y_train)
knn.score(X_test,y_test)

#将6种动作的图片通过plt绘制线性图,每个动作随即取自取一个样本,所有的图一起打印
#一共2行,每行3张图片 每张图片的大小为6*6

plt.figure(figsize=(3*6,2*6))for i in range(6):#编号axes = plt.subplot(2,3,i+1)#执行随即抽样  np,argwhere()nd_index = np.argwhere(y_test == i+1).ravel()#随即获取一个样  只能randomindex = nd_index[np.random.randint(0,nd_index.size,1)[0]]axes.plot(X_test[index])#添加标题axes.set_title(label[i+1])#标题更换为真实的值和预测#y_test    y_axes.set_title('True:%s\nPredict:%s'%(label[y_test[index]],label[y_[index]]))

图片略

5、手写单张图片数字识别

import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_splitzero = plt.imread('./knn_num_data/0/0_1.bmp')
plt.imshow(zero,cmap='gray')zero.shapepath = './knn_num_data/%d/%d_%d.bmp'
#首先引入所有的数据集
#使用循环
data = []
target = []for i in range(10):for j in range(500):im_data = plt.imread(path%(i,i,j+1))data.append(im_data)target.append(i)
data = np.array(data)
data.shape
#机器学习的数据必须是二维的
data_ = data.reshape(5000,-1)
data_.shape#(5000, 28*28)
len(target)
#分割数据
X_train,X_test,y_train,y_test = train_test_split(data_,target,test_size=0.01)#1.建立模型
knn = KNeighborsClassifier()
knn.fit(X_train,y_train)#2.评估和预测
knn.score(X_train,y_train)#进行预测
y_ = knn.predict(X_test)
knn.score(X_test,y_test)
#将刚才的50张预测全部打印  设置标题,写一个真实的值,写一个预测的值 ,看出那些数字的写法容易让分类识别错误
#图片的大小为3*3的  10行 5列plt.figure(figsize=(3*5,4*10))for i in range(50):#图片的编号已经显示方式axes = plt.subplot(10,5,i+1)#打印图片axes.imshow(X_test[i].reshape(28,28))#取消刻度axes.axis('off')#设置标题axes.set_title('True:%s\nPredict:%s'%(y_test[i],y_[i]))

图片略

6、knn边界散点图

import numpy as np
import matplotlib.pyplot as pltfrom sklearn.neighbors import KNeighborsClassifier
import sklearn.datasets as datasetsdata = datasets.load_iris()['data']
target = datasets.load_iris()['target']#画一个散点图
data_ = data[:,:2] #花萼的散点图
plt.scatter(data_[:,0],data_[:,1],c=target,cmap='cool')petal = data[:,2:]#花瓣的散点图
plt.scatter(petal[:,0],petal[:,1],c=target)

给分类线制造一些数据

生成40000点,用点把整个画布全部覆盖,然后将这些点进行机器学习,最终会得到预测值,根据预测结果画图

x = np.linspace(4,8.2,200)
y = np.linspace(1.8,4.5,200)#绘制网格线
xx,yy = np.meshgrid(x,y)#将xx,yy的数据合并成点  np.c_[]:将两个一维的数据合并成一个两维的数据
X_test = np.c_[xx.ravel(),yy.reshape(-1)]X_test#建立knn的模型
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(data_,target)#进行预测取结果
y_ = knn.predict(X_test)plt.scatter(X_test[:,0],X_test[:,1],c=y_)
plt.scatter(data_[:,0],data_[:,1],c=target,cmap='cool')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JVXGhW7V-1592462080590)(数据分析图片/边界散点图.png)]

七、特征工程

1、特征工程简介

1.特征工程是什么?

特征工程就是将原始的数据转换为更好地代表预测模型的潜在问题的特征过程,从而提高对未知数据的预测准确率(增加了模型的泛化能力)比如资讯APP要对文章进行分类,那么直接把文章拿过去学习,那机器怎么能认识了。我们可以将文字映射成数字,然后提取关键的字,提高分类的准确性

2.特征工程的意义是什么?

直接影响预测的结果

2、sklearn特征抽取API

1.字典特征提取

from sklearn.feature_extraction import DictVectorizer
def dictvec():#sparse  稀松矩阵  大部分是0   小部分数据位置是其他值dict_ = DictVectorizer(sparse=False)data = [{'city':'北京','temperature':100},{'city':'上海','temperature':60},{'city':'深圳','temperature':40},]#处理数据data_=dict_.fit_transform(data)print(data_)print(dict_.transform(data))#反转数据用什么类型值print(dict_.inverse_transform(data_))#返回特征值名称print(dict_.get_feature_names())dictvec()

2.文本特征的提取

词频=某一个词语在文章中出现的次数

(1)英文文本

from sklearn.feature_extraction.text import CountVectorizerdef countvec():cv_= CountVectorizer()data=['life is short small,use python','life is is long,not need python']#处理数据res=cv_.fit_transform(data)print(res)#返回特征值名称print(cv_.get_feature_names())#词频print(res.toarray())
countvec()    

(2)中文文本

from sklearn.feature_extraction.text import CountVectorizer
def countvec_zn():cv_= CountVectorizer()data=['人生苦短我做python','人生苦长不用python']#处理数据res=cv_.fit_transform(data)print(res)#返回特征值名称print(cv_.get_feature_names())#词频print(res.toarray())
countvec_zn()    

(3)中文分词

import jieba
def cutword():#中文文本con1 =jieba.cut('长得,长得,丑怎么了,我自己又看不到,恶心的是你们')con2 =jieba.cut('时间是把杀猪刀,这句话只适用于长得好看的人')con3 =jieba.cut('你在知乎领悟了什么?领悟到小时候不好好学习,长大了只会给被人点赞')print(con1)#返回一个迭代器对象content1=list(con1)content2=list(con2)content3=list(con3)print(content1)#拼接   ‘ ’.join()c1 = ' '.join(content1)c2 = ' '.join(content2)c3 = ' '.join(content3)print(c1)return [c1,c2,c3]def hanzivec():cv_=CountVectorizer()list_=cutword()#中文转变为词向量   单个字符的字不提示res=cv_.fit_transform(list_)print(res)#获取中文分词特征print(cv_.get_feature_names())#转变为词向量   这是一个稀松矩阵相加的值print(res.toarray())
hanzivec()   

3.统计词语

from sklearn.feature_extraction.text import TfidfVectorizer
def tfidfvec():list_ = cutword()tf = TfidfVectorizer()#处理数据res=tf.fit_transform(list_)#返回特征值名称print(1,tf.get_feature_names())#计数print(res.toarray())print(res)
tfidfvec()    

3、数据的预处理

通过特定的统计方法(数学方法)将数据转换成算法要求的数据

import numpy as np
nd = np.array([[90,2,10,40],[60,4,15,45],[75,3,13,46]])
nd

1.数据归一化

目的:让某一列数值非常大的数值不对其它列造成过大的影响

特点:通过对原始数据进行变换把数据映射到 (默认为)0-1 之间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EmqCvOej-1592462080592)(数据分析图片/归一化.jpg)]

注意:归一化的作用范围是每一列,max是每一列中的最大值,min是每一列中的最小值,那么X‘’为最终的结果。mx,mi分别是指定范围的值,默认mx为1,mi为0

归一化的缺点:对数据中含有异常值的处理非常不理想

归一化总结:在特定场景下最大值和最小值是变化的,另外,在最大值最小值非常容易受异常点影响,所以这种方法的鲁棒性(稳定性)较差,只适合传统精确小数据场景。

from sklearn.preprocessing import  MinMaxScaler
def normal():nd = np.array([[90,2,10,40],[60,4,15,45],[75,3,13,46]])#实例化归一化方法(归一化数据范围)nm=MinMaxScaler(feature_range=(0,1))#处理数据result=nm.fit_transform(nd)print(result)
normal()
# 归一化  将每一列数据重要性变得相同

2.数据标准化

标准化是 是列中的每一个元素 减去 该列的平均值 除以该列的标准差 因为均值,大部分数据是正常的,只有小部分的数据是异常值。不影响数据波动 除以标准差的作用是将值压缩的更小,方差、标准差的计算也是受到均值的影响的。

特点:通过对原始数据进行变换把数据变换到均值为0,方差为1的范围内

标准化总结:在已有样本足够多的情况下比较稳定,适合现代嘈杂大数据的场景。

对于归一化来说:如果出现异常点,影响了最大值和最小值,那么结果显然会发生改变

对于标准化来说:如果出现异常点,由于具有一定的数据量,少量的异常点对于平均值得影响不大,方差的改变也比较的小

删除:如果某一列或者某一行数据缺失值的比例较大,建议放弃整行或者整列

插补:通过每行或者每列的平均值,或者中位数(中值)来填充,在特定的情况也可以补0

from sklearn.preprocessing import StandardScaler
def stand():std_ = StandardScaler()#创建标准化处理对象nd = np.array([[90,2,10,40],[60,4,15,45],[75,3,13,46]])#标准化处理数据result = std_.fit_transform(nd)#输出标准化处理结果 print(result)#数据的平均值print(std_.mean_)#方差(标准差std_.var_**0.5)print()stand()

3.处理缺失值

NaN就是缺失值

from sklearn.preprocessing import Imputer
import  pandas as pddef im(X):#Imputer和pandas.fillna()只能识别NaN,不能识别其他类型特殊字符im = Imputer(missing_values='NaN', strategy='median', axis=1)X_ =  pd.DataFrame(X)dict_={'??':np.nan,'?':np.nan}X_=X_.replace(dict_)result = im.fit_transform(X_)print(result)nd_ = np.array([[1,2,3,4],[2,'??',3,7],[9,10,'?',0]])
im(nd_)

4.特征选择

特征选择就是单纯地从提取到的所有特征中选择部分特征作为训练集特征在选择前和选择后可以改变值,也可以不改变值,但是在选择后的特征维度肯定要比选择之前小,毕竟我们只选择了其中的一部分特征。

特征冗余:部分特征的相关度高,容易消耗计算性能

噪音:部分特征对预测的结果会产生比较大的影响

from sklearn.feature_selection import VarianceThreshold
def var_():#PCA在实际工作中,用的都比较少,因为可以用经验来判断vt = VarianceThreshold()#data = pd.DataFrame({'数学':[100,101,102,103],'语文':np.random.randint(0,100,4)})#data['物理'] = data['数学'].map(lambda x : x*1.2)data=np.array([[1,2,3,4],[1,3,2,4],[1,2,3,4]])result = vt.fit_transform(data)print(result)
var_()

5.PCA降维

PCA叫做主成分分析,主成分就是各个特征
降维,在机器学习中一列就是一个维度,降维就是减少特征数量
结构化数据 相当于mysql的表类型
半结构化数据 xml html
非结构化数据 图片 28*28
PCA对于非结构化的数据非常有用,人脸识别,图片越清晰,像素就越高,维度越多计算的越慢
9w维度降成300维度,每列之间多多少少都会有某一种关系,协方差矩阵,协方差值越高,说明关系越密切,线性代数中的正交基,基变换以后是值放大了的稀松矩阵
被pca降维以后的特征,我们认为这些特征之间的关系是独立不相关

本质:PCA是一种简化,分析数据的一种技术

目的:是数据维度数量的压缩,尽可能降低原数据的维度数量,减少重合数据的损失(维度数量越少,数据的复杂度就越低)

作用:减少特征的数量,减少特征之间的相关性,提高准确度和计算效率

from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
def pca():cat = plt.imread('./cat.jpg')print(cat.reshape(-1).shape)pca_ = PCA(n_components=150, copy=True, whiten=True)#pca处理的数据应当是二维的X_train = cat.reshape(456,-1)print(X_train.shape)res = pca_.fit_transform(X_train)print(res.shape)#降维要求所有的图片大小必须一致#人脸识别
pca()

八、线性回归

1、普通线性回归

1.原理

y(x)= ax1 + bx2 + …… + zxn + num,也就是给定训练数据X_train=(x1,x2,x3……)和正确值y_train=y(x)一一对应的值去做训练,求取x1,x2,等前面系数的值,以及num常数项的值。

2.实现

使用线性回归分析糖尿病数据,不可评估

from sklearn.linear_model import LinearRegression
import sklearn.datasets as datasets
import numpy as np#获取数据
diabetes = datasets.load_diabetes()
#age  sex  bmi体重  bp血压  s1-s6血清
data=diabetes['data']
target = diabetes['target']#直接使用机器学习,直接求解系数和误差值
lrg = LinearRegression()#一共有10列系数,每一列都会有一个系数,也就是x前面的系数
lrg.coef_#获取偏执项,也就是常数项
lrg.intercept_

2、岭回归 L2范数

1.原理

小数据、多特征。

缩减方法可以去掉不重要的参数,因此能更好地理解数据。L2范数在计算 系数的 时候 考虑的是 先接近于0 ,在慢慢增长(梯度上升)

2.实现

from sklearn.linear_model import RidgeX = np.random.randint(0,150,size=(3,5))
y = 3* X[:,0] + 5 * X[:,1] + 3 * X[:,2] + 10 * X[:,3] + 3 * X[:,4]#实例化岭回归
#alpha=1.0  = lambda
#fit_intercept=True  默认有偏执项的
rg = Ridge(fit_intercept=False,alpha=0.01)
rg.fit(X,y)#系数
rg.coef_
#常数项
rg.intercept_

3.岭迹线范畴

#岭迹线 是 lambda的取值范围    也就是alpha的取值范围   使得求出的各个列的预测系数更贴近真实值。
X = 1/(np.arange(10) + np.arange(1,11).reshape(10,1))
y = np.ones(10)#alpha先不设定
rg = Ridge(fit_intercept=False)
alphas = np.logspace(-10,0,10) 
res = []for i in alphas:#设置岭回归的惩罚系数的值rg.set_params(alpha=i)rg.fit(X,y)res.append(rg.coef_)import matplotlib.pyplot as plt
plt.figure(figsize=(18,12))
plt.plot(alphas,res)
#修改刻度轴
plt.xscale('log')
#获取当前的画布对象
axes = plt.axes()
plt.grid()
plt.xlim(axes.get_xlim()[::-1])

根据图像分析,选取中间部分,该数据的alpha应该靠近0.001左右更适合。

3、 罗斯回归 L1范数

小数据、少特征的数据集。

X = 1/(np.arange(10) + np.arange(1,11).reshape(10,1))
y = np.ones(10)#罗斯回归
la = Lasso(fit_intercept=False,alpha=0.020)
la.fit(X,y)
la.coef_

4、识别趋势

from sklearn.neighbors import KNeighborsRegressordata = np.linspace(0,10,50)
target = np.sin(data)#添加噪音
target[::5] += np.random.randn(10) * 0.35plt.scatter(data,target)knn_R = KNeighborsRegressor()
knn_R.fit(data.reshape(50,1),target)X_test = np.linspace(0,10,50)
y_test = np.sin(data)y_ = knn_R.predict(X_test.reshape(50,1))plt.scatter(data,target)
plt.plot(X_test,y_)

九、逻辑回归

1、逻辑斯蒂回归

1.原理

假如有一个罐子,里面有黑白两种颜色的球,数目多少不知,两种颜色的比例也不知。我 们想知道罐中白球和黑球的比例,但我们不能把罐中的球全部拿出来数。现在我们可以每次任意从已经摇匀的罐中拿一个球出来,记录球的颜色,然后把拿出来的球 再放回罐中。这个过程可以重复,我们可以用记录的球的颜色来估计罐中黑白球的比例。假如在前面的一百次重复记录中,有七十次是白球,请问罐中白球所占的比例最有可能是多少?很多人马上就有答案了:70%。而其后的理论支撑是什么呢?

我们假设罐中白球的比例是p,那么黑球的比例就是1-p。
因为每抽一个球出来,在记录颜色之后,我们把抽出的球放回了罐中并摇匀,
所以每次抽出来的球的颜 色服从同一独立分布。
这里我们把一次抽出来球的颜色称为一次抽样。题目中在一百次抽样中,
七十次是白球的概率是P(Data | M),这里Data是所有的数据,
M是所给出的模型,表示每次抽出来的球是白色的概率为p。
如果第一抽样的结果记为x1,第二抽样的结果记为x2... 
那么Data = (x1,x2,…,x100)。这样,

P(Data | M)

= P(x1,x2,…,x100|M)

= P(x1|M)P(x2|M)…P(x100|M)

= p70(1-p)30.

那么p在取什么值的时候,P(Data |M)的值最大呢?将p70(1-p)30对p求导,并其等于零。

70p69(1-p)30-p70*30(1-p)29=0。

解方程可以得到p=0.7。

在边界点p=0,1,P(Data|M)=0。所以当p=0.7时,P(Data|M)的值最大。这和我们常识中按抽样中的比例来计算的结果是一样的。

2.简单代码实现

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split#导入数据load_digits()
num = datasets.load_digits()data = num['data']
target = num['target']#显示数据
plt.figure(figsize=(0.5,0.5))
plt.imshow(data[5].reshape(8,8),cmap='gray')#将数据切分  1797
X_train,X_test,y_train,y_test = train_test_split(data,target,test_size=0.01)#实例化
lor = LogisticRegression()  #C = 岭回归的中alpha   penalty='l2' 这是正则化参数  tol=0.0001  梯度下降的精确值 
#排雷 步伐 越小越好,越精确
lor.fit(X_train,y_train)lor.score(X_train,y_train)
y_=lor.predict(X_test)
lor.score(X_test,y_test)

3.数据集进行分类

import numpy as np
import sklearn.datasets as datasets#创建数据
#make_blobs 就是用来创建点的
#n_samples=100, n_features=2, centers=3 生成3类数据  返回一个元祖 第一个元素是特征值  第二个元素是目标值
#cluster_std 每个类型点的标准差,标准差越小,点越聚合
data,target = datasets.make_blobs(n_samples=102,cluster_std=1.2)#画一个散点图
plt.scatter(data[:,0],data[:,1],c=target)#需要很多的点铺满整个画布,再对这些点进行预测  150*200 = 3w
x = np.linspace(-1,11,200)
y = np.linspace(-13,6,150)#meshgrid 返回全为x轴的数据 和 全为y轴的数据
xx,yy = np.meshgrid(x,y) 
xy = np.concatenate([xx.ravel().reshape(-1,1),yy.ravel().reshape(-1,1)],axis=1)#建立模型
lr_ = LogisticRegression()
lr_.fit(data,target)#评分
lr_.score(data,target)#数据测试
y_ = lr_.predict(xy)#线性分类的分类线为什么平整,因为先求的线性回归
plt.scatter(xy[:,0],xy[:,1],c=y_,cmap='cool')
plt.scatter(data[:,0],data[:,1],c=target,cmap='gray')

4.梯度下降

from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression,SGDRegressor   #一个是普通的方程,一个是带有梯度下降的方程
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
#对回归进行评估  mse  
from sklearn.metrics import mean_squared_error#1.引入数据
lb = load_boston()#一共506个样本,13列值 
lb.data.shape#2.将数据切割
X_train,X_test,y_train,y_test = train_test_split(lb.data,lb.target,test_size=0.1)#3.将特征值标准化
std_x = StandardScaler()
X_train = std_x.fit_transform(X_train)
X_test = std_x.transform(X_test)
#将目标值标准化
std_y  = StandardScaler()
y_train = std_y.fit_transform(y_train.reshape(-1,1))
y_test  = std_y.transform(y_test.reshape(-1,1))#4.建立模型   逻辑回归
lr = LinearRegression()
lr.fit(X_train,y_train)
#测试
y_lr = lr.predict(X_test)
#获取求解的系数
lr.coef_
#获取偏执值
lr.intercept_#建立模型    使用梯度下降的方程
sgd = SGDRegressor()
sgd.fit(X_train,y_train)
#测试
y_sgd = sgd.predict(X_test)
#获取求解的系数
sgd.coef_
#获取偏执值
sgd.intercept_

5.多目标值简化项目

import numpy as np
import pandas as pd
from pandas import DataFrame
#knn+逻辑
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
#标准化
from sklearn.preprocessing import StandardScaler#1.引入葡萄酒的数据集
white_ = pd.read_csv('winequality-white.csv',sep=';')
white_['quality'].unique() #品质从3-9 一共7个类别data = white_.iloc[:,:-1]
target = white_.iloc[:,-1]#实例化标准化方法
std_ = StandardScaler()
data_ = std_.fit_transform(data)#切割数据
X_train,X_test,y_train,y_test = train_test_split(data_,target,test_size=0.01)#2.建立逻辑模型
lr = LogisticRegression()
lr.fit(X_train,y_train)#3.评估和预测
lr.score(X_train,y_train)
lr.coef_.shape  #7中分类  11def convert2level(quality):if quality <=4:return 'low'elif quality >= 8:return 'high'else:return 'median'#因为分类太多,准确率就会不高,怎么解决?
#答:数据分箱,实际上就是将相同的小类别合并成一个大类别
#3-9 一共7个类别  3,4 分为 low   5,6,7分为 median  8,9分为 high  .map()  
white_['quality'] = white_['quality'].map(convert2level)#重新取值
data = white_.iloc[:,:-1]
target = white_.iloc[:,-1]#重新标准化
std_ = StandardScaler()
data_ = std_.fit_transform(data)#重新切割数据
X_train,X_test,y_train,y_test = train_test_split(data_,target,test_size=0.01)#重新训练
lr.fit(X_train,y_train)
lr.score(X_train,y_train)
y_lr = lr.predict(X_test)
lr.score(X_test,y_test)

2、决策树

1.决策树的原理

决策树(decision tree)是一个树结构(可以是二叉树或非二叉树)。其每个非叶节点表示一个特征属性上的测试,每个分支代表这个特征属性在某个值域上的输出,而每个叶节点存放一个类别。使用决策树进行决策的过程就是从根节点开始,测试待分类项中相应的特征属性,并按照其值选择输出分支,直到到达叶子节点,将叶子节点存放的类别作为决策结果。

2.决策树的构造

不同于逻辑斯蒂回归和贝叶斯算法,决策树的构造过程不依赖领域知识,它使用属性选择度量来选择将元组最好地划分成不同的类的属性。所谓决策树的构造就是进行属性选择度量确定各个特征属性之间的拓扑结构。构造决策树的关键步骤是分裂属性。所谓分裂属性就是在某个节点处按照某一特征属性的不同划分构造不同的分支,其目标是让各个分裂子集尽可能地“纯”。尽可能“纯”就是尽量让一个分裂子集中待分类项属于同一类别。分裂属性分为三种不同的情况:
1、属性是离散值且不要求生成二叉决策树。此时用属性的每一个划分作为一个分支。
2、属性是离散值且要求生成二叉决策树。此时使用属性划分的一个子集进行测试,按照“属于此子集”和“不属于此子集”分成两个分支。
3、属性是连续值。此时确定一个值作为分裂点split_point,按照>split_point和<=split_point生成两个分支。
构造决策树的关键性内容是进行属性选择度量,属性选择度量是一种选择分裂准则,它决定了拓扑结构及分裂点split_point的选择。属性选择度量算法有很多,一般使用自顶向下递归分治法,并采用不回溯的贪心策略。这里介绍常用的ID3算法。

3、ID3算法

日志密度/L 好友密度/F 真实头像/H 真实账户/R
S S NO NO
S L YES YES
L M YES YES
M M YES YES
L M YES YES
M L NO YES
M S NO NO
L M NO YES
M S NO YES
S S YES NO

表中S、M和L分别表示小、中和大。

设L、F、H和R表示日志密度、好友密度、是否使用真实头像和账号是否真实,试用ID3算法构造决策树。

import numpy as np
解:设D为10个样本集,其中决策属性(真实账户/R)有7个YES、3个NO。决策属性信息熵为:
info_D = -(0.7*np.log2(0.7)+0.3*np.log2(0.3))
#日志密度属性期望信息熵为:#占总列 下同  对应真实账户yes/no占总个数的比例    	
info_L_D = -(0.3*(1/3*np.log2(1/3)+2/3*np.log2(2/3))+0.3*(np.log2(1))+0.4*(1/4*np.log2(1/4)+3/4*np.log2(3/4)))
#好友密度属性期望信息熵为:
info_F_D = -(0.4*(1/4*np.log2(1/4)+3/4*np.log2(3/4))+0.4*(np.log2(1))+0.2*(np.log2(1)))
#真实头像属性期望信息熵为:
info_H_D= - (0.5*  (4/5*np.log2(4/5)+1/5*np.log2(1/5))+0.5*((3/5*np.log2(3/5)+2/5*np.log2(2/5))))

如果使用是id这个字段作为根,那么所有的数据都是叶子节点

4、C4.5算法

1. C4.5算法简介

C4.5算法是用于生成决策树的一种经典算法,是ID3算法的一种延伸和优化。

C4.5算法对ID3算法主要做了一下几点改进:

(1)通过信息增益率选择分裂属性,克服了ID3算法中通过信息增益倾向于选择拥有多个属性值的属性作为分裂属性的不足;

(2)能够处理离散型和连续型的属性类型,即将连续型的属性进行离散化处理;

(3)构造决策树之后进行剪枝操作;

(4)能够处理具有缺失属性值的训练数据。

2. 分裂属性的选择——信息增益率

分裂属性选择的评判标准是决策树算法之间的根本区别。

区别于ID3算法通过信息增益选择分裂属性,C4.5算法通过信息增益率选择分裂属性。

CART(classificationandregressiontree), 分类回归树算法,既可用于分类也可用于回归,在这一部分我们先主要将其分类树的生成。区别于ID3和C4.5,CART假设决策树是二叉树,内部节点特征的取值为“是”和“否”,左分支为取值为“是”的分支,右分支为取值为”否“的分支。这样的决策树等价于递归地二分每个特征,将输入空间(即特征空间)划分为有限个单元。CART的分类树用基尼指数来选择最优特征的最优划分点,具体过程如下 使用GINI系数作为衡量标准:

3.代码实现

【注意】 参数max_depth越大,越容易过拟合

#预剪枝 在决策树 开始计算的之前 , 给一个深度
#后剪枝 在计算过程中,设定叶节点的数量

import numpy as np
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
#GridSearchCV   GridSearch网格搜索   CV交叉验证(缩写)
from sklearn.model_selection import train_test_split,GridSearchCV
#标准化   决策树不需要任何数据做数据标准化,空数据对于决策树的影响是非常非常小的。
#pydotplus 画图工具库 可以画出决策树
#tree  决策树在画图时候需要依赖tree包
import sklearn.tree as tree
from sklearn.externals.six import StringIO
import pydotplus#加载处理数据
iris = load_iris()
data = iris['data']
target = iris['target']#切割数据
X_train,X_test,y_train,y_test=train_test_split(data,target,test_size=0.1)#如果  max_depth 是树的深度,层次数量太多,很容易发生   过拟合  泛化性不强
tree_ = DecisionTreeClassifier(criterion='entropy',max_depth=2)
tree_.fit(X_train,y_train)#打印决策树
st_ = StringIO()
"""
export_graphviz()
第一个参数是 decision_tree 决策树的实例  tree_
第二个参数是 out_filt 代表使用的打印工具  st_
第三个参数是 feature_names 数据的特征 写的是数据集的原始对象 iris.feature_names,
第四个参数是 class_names 数据中分类的名字  iris.target_names,
"""
tree.export_graphviz(tree_,out_file=st_,feature_names=iris.feature_names,class_names=iris.target_names,filled=True,rounded=True)
# 调用画图工具
graph = pydotplus.graph_from_dot_data(st_.getvalue())
#输出图片
graph.write_pdf('iris.pdf')
#评估
tree_.score(X_train,y_train)
tree_.score(X_test,y_test)

5、随机森林

多个决策树组合成森林

随机森林是混合算法
随机森林中建立五个决策树,4个将数据定为A类,1个定为B类,少数服从多数

随机森林的优点:
1、在当前的所有算法中,具有极好的准确率
2、能够在大数据的场景下有效的发挥
3、能够处理高维特征的数据,不需要降维
4、可以评估各种类型的特征

from sklearn.ensemble import RandomForestClassifier
# n_estimators 估计器=算法的模型  生成决策树的数量
rfc = RandomForestClassifier()
# estimator,  估计器的实例对象
# param_grid,  是一个字典  字典当中是参数调优的值
param = {'n_estimators':[120,200,300,500,800,1200],'max_depth':[1,2,3,4]}
gc = GridSearchCV(rfc,param_grid=param,cv=2)
gc.fit(X_train,y_train)#返回最好的参数
gc.best_params_
#返回最好的随机模型
gc.best_estimator_
gc.best_score_

十、朴素贝叶斯分类

优点:

  • 朴素贝叶斯模型发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率;
  • 对小规模的数据表现很好;
  • 能处理多分类任务,适合增量式训练;
  • 对缺失数据不太敏感,算法也比较简单,常用于文本分类

缺点:

  • 只能用于分类问题
  • 需要计算先验概率;
  • 分类决策存在错误率;
  • 对输入数据的表达形式很敏感

1、高斯分布朴素贝叶斯

高斯分布就是正态分布

import sklearn.datasets as datasets
from sklearn.naive_bayes import GaussianNB,MultinomialNB,BernoulliNB
from sklearn.model_selection import train_test_split
data = datasets.load_iris()['data']
target = datasets.load_iris()['target']
X_train,X_test,y_train,y_test=train_test_split(data,target,test_size=0.1)
GNB =  GaussianNB()
GNB.fit(X_train,y_train)
GNB.score(X_train,y_train)
GNB.score(X_test,y_test)

2、多项式分布朴素贝叶斯

适用于文本数据(特征表示的是次数,例如某个词语的出现次数)

import sklearn.datasets as datasets
from sklearn.naive_bayes import GaussianNB,MultinomialNB,BernoulliNB
from sklearn.model_selection import train_test_split
MNB = MultinomialNB()
MNB.fit(X_train,y_train)
MNB.score(X_train,y_train)
MNB.score(X_test,y_test)

3、伯努利分布朴素贝叶斯

【用途】适用于伯努利分布,也适用于文本数据(此时特征表示的是是否出现,例如某个词语的出现为1,不出现为0)

绝大多数情况下表现不如多项式分布,但有的时候伯努利分布表现得要比多项式分布要好,尤其是对于小数量级的文本数据

import sklearn.datasets as datasets
from sklearn.naive_bayes import GaussianNB,MultinomialNB,BernoulliNB
from sklearn.model_selection import train_test_splitBNB = BernoulliNB()
BNB.fit(X_train,y_train)
BNB.score(X_train,y_train)
BNB.score(X_test,y_test)

4、文本分类实战

导包
导入sklearn.feature_extraction.text.TfidfVectorizer用于转换字符串
读取短信数据

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizersms = pd.read_csv('./day12_data/SMSSpamCollection',sep='\t',header=None)
#将目标值 和 特征值提取出来
data = sms[1]
target = sms[0]
#转成one-hot编码  稀松矩阵
tfidf = TfidfVectorizer()
text_vector = tfidf.fit_transform(data)
#5572个文本  8713个单词  一共使用74169个单词
text_vector#获取特征名称,文本的特征就是单词
tfidf.get_feature_names()
text_vector.toarray()
#目标值array(['ham', 'ham'],
X_test = ["Did you catch the bus ? Are you frying an egg ? Did you make a tea? Are you eating your mom's left over dinner ? Do you feel my Love ? go die.","Thanks for your subscription to Ringtone UK your mobile will be charged £5/month Please confirm by replying YES or NO. If you reply NO you will not be charged!kill you"]
X_test  = tfidf.transform(X_test)

多项式

MNB = MultinomialNB()
MNB.fit(text_vector,target)
MNB.score(text_vector,target)
MNB.predict(X_test)

伯努利

BNB = BernoulliNB()
BNB.fit(text_vector,target)
BNB.score(text_vector,target)
BNB.predict(X_test)

高斯

GNB = GaussianNB()
#高斯贝叶斯不认识稀松矩阵
GNB.fit(text_vector.toarray(),target)
GNB.score(text_vector.toarray(),target)
GNB.predict(X_test.toarray())

十一、支持向量机SVM

1、支持向量机的原理

Support Vector Machine。支持向量机,其含义是通过支持向量运算的分类器。其中“机”的意思是机器,可以理解为分类器。 那么什么是支持向量呢?在求解的过程中,会发现只根据部分数据就可以确定分类器,这些数据称为支持向量。 见下图,在一个二维环境中,其中点R,S,G点和其它靠近中间黑线的点可以看作为支持向量,它们可以决定分类器,也就是黑线的具体参数。

解决的问题:

  • 线性分类

在训练数据中,每个数据都有n个的属性和一个二类类别标志,我们可以认为这些数据在一个n维空间里。我们的目标是找到一个n-1维的超平面(hyperplane),这个超平面可以将数据分成两部分,每部分数据都属于同一个类别。 其实这样的超平面有很多,我们要找到一个最佳的。因此,增加一个约束条件:这个超平面到每边最近数据点的距离是最大的。也成为最大间隔超平面(maximum-margin hyperplane)。这个分类器也成为最大间隔分类器(maximum-margin classifier)。 支持向量机是一个二类分类器。

  • 非线性分类

SVM的一个优势是支持非线性分类。它结合使用拉格朗日乘子法和KKT条件,以及核函数可以产生非线性分类器。

SVM的目的是要找到一个线性分类的最佳超平面 f(x)=xw+b=0。求 w 和 b。

首先通过两个分类的最近点,找到f(x)的约束条件。

有了约束条件,就可以通过拉格朗日乘子法和KKT条件来求解,这时,问题变成了求拉格朗日乘子αi 和 b。

对于异常点的情况,加入松弛变量ξ来处理。

非线性分类的问题:映射到高维度、使用核函数。

线性分类及其约束条件:

SVM的解决问题的思路是找到离超平面的最近点,通过其约束条件求出最优解。

2、实战

1.画出决策边界

from sklearn.svm import SVC
import numpy as np
import matplotlib.pyplot as pltnd1 = np.random.randn(20,2)-[2,2]
nd2 = np.random.randn(20,2)+[3,2]print(nd1,'\n\n\n',nd2)
dot = np.concatenate([nd1,nd2])
dot#给数据设置目标值
target = [0]*20 + [1]*20
target#绘制分布图
plt.scatter(dot[:,0],dot[:,1],c=target)#训练模型,并训练
# kernel  核函数 rbf 基于半径
svc = SVC(kernel='linear')
X_train = dot
y_train = target
svc.fit(X_train,y_train)
#获取参数
coef_=svc.coef_
b_=svc.intercept_
#提供支持向量(过线点的位置坐标)
support_vectors_ = svc.support_vectors_
plt.scatter(support_vectors_[:,0],support_vectors_[:,1],s=100,c='pink',alpha=0.8)
plt.scatter(dot[:,0],dot[:,1],c=target)#求分界线方程系数y=wx+b
w = -(coef_[:,0]/coef_[:,1])
b = -(b_/coef_[:,1])
X = np.linspace(-6,5,100)
y=w*X+b
#划分界线
plt.scatter(support_vectors_[:,0],support_vectors_[:,1],s=100,c='pink',alpha=0.8)
plt.scatter(dot[:,0],dot[:,1],c=target)
plt.plot(X,y)#绘制三维图形
from mpl_toolkits.mplot3d import Axes3D
x1 = X_train[:,0]
y1 = X_train[:,1]
w1= coef_[:,0]
w2= coef_[:,1]z = w1*x1+w2*y1+b_
#绘制三维图片
fig = plt.figure(figsize=(10,10))
#实例化3d模块
axes3d = Axes3D(fig)
#绘制3d散点图
axes3d.scatter3D(x1,y1,z,c=y_train,cmap='rainbow')
#绘制超图片
axes3d.plot_surface(X,y,z.reshape(-1,1),color='pink',alpha=0.3)#绘制过点线
#第一个点和最后一个点是肯定没有关系
support_vectors_
#获取图片上方的点
vector_up = support_vectors_[-1]
vector_down = support_vectors_[0]
#计算点到分类线之间的距离 
#y = wx + b 
#b = y - wx
y_up = w * X +(vector_up[1] - w*vector_up[0])
y_down = w * X +(vector_down[1] - w*vector_down[0])
plt.scatter(support_vectors_[:,0],support_vectors_[:,1],s=200,c='pink',alpha=0.5)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
plt.plot(X,y)
plt.plot(X,y_up,X,y_down)

2.SVM分离坐标点

data = np.random.randn(300,2)
plt.scatter(data[:,0],data[:,1])
target = np.logical_xor(data[:,0]>0,data[:,1]>0) 
plt.scatter(data[:,0],data[:,1],c=target)
svc = SVC()
svc.fit(data,target)
#生成测试数据
x = np.linspace(-3,3.2,200)
y = np.linspace(-3,3.2,150)xx,yy = np.meshgrid(x,y)
xy = np.c_[xx.ravel(),yy.ravel()]
#预测
y_ = svc.predict(xy)
svc.score(data,target)plt.scatter(xy[:,0],xy[:,1],c=y_)
plt.scatter(data[:,0],data[:,1],c=target,cmap='cool')
plt.contour(xx,yy,z.reshape(150,200))#使用svm中自动的合成函数 
z = svc.decision_function(xy)
z.shape#第三个轴必须是二维
plt.contourf(xx,yy,z.reshape(150,200))#svm   3d图形
fig = plt.figure(figsize=(10,10))
axes3d = Axes3D(fig)
axes3d.plot_surface(xx,yy,z.reshape(150,200),cmap='rainbow')

3.多种核函数对数据分类

from sklearn.datasets import load_irisdata = load_iris()['data'][:,:2]
target = load_iris()['target']
data.shapeli_ = ['linear','poly','rbf']
model_ ={}for i in range(len(li_)):model_[li_[i]]=SVC(kernel=li_[i])
for i in model_:model_[i]=model_[i].fit(data,target)
plt.scatter(data[:,0],data[:,1],c=target)#创建预测的数据 30000
x = np.linspace(4,8.1,200)
y = np.linspace(1.9,4.5,150)
xx,yy=np.meshgrid(x,y)
xy = np.c_[xx.ravel(),yy.ravel()]
xy.shaperes={}
for i in model_:res[i] = model_[i].predict(xy)plt.figure(figsize=(12,10))
for i,k in enumerate(res):axes = plt.subplot(2,2,i+1)axes.contourf(xx,yy,res[k].reshape(150,200),cmap='cool')axes.scatter(data[:,0],data[:,1],c=target)

4.SVM多种核函数回归

from sklearn.svm import SVRX = np.linspace(0,10,100)
y = np.sin(x)
y[::4] += np.random.randn(25)*0.35
plt.scatter(X,y)X_test = np.linspace(0,10,200).reshape(-1,1)li_ = ['linear','poly','rbf']
model_ = {}for i in range(len(li_)):model_[li_[i]] = SVR(kernel=li_[i]).fit(X.reshape(-1,1),y)plt.figure(figsize=(12,8))
plt.scatter(X,y)
for i in res_:plt.plot(X_test,res_[i],label=i)plt.legend()

十二、K均值算法 聚类

1、K-means算法原理

K-Means算法是一种聚类分析(cluster analysis)的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法。

K-Means算法主要解决的问题如下图所示。我们可以看到,在图的左边有一些点,我们用肉眼可以看出来有四个点群,但是我们怎么通过计算机程序找出这几个点群来呢?于是就出现了我们的K-Means算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-stNZzxY6-1592462080594)(数据分析图片/k-meansgif)]

K-Means主要最重大的缺陷——都和初始值有关:

K是事先给定的,这个K值的选定是非常难以估计的。很多时候,事先并不知道给定的数据集应该分成多少个类别才最合适。(ISODATA算法通过类的自动合并和分裂,得到较为合理的类型数目K)

K-Means算法需要用初始随机种子点来搞,这个随机种子点太重要,不同的随机种子点会有得到完全不同的结果。(K-Means++算法可用来解决这个问题,其可以有效地选择初始点)

总结:K-Means算法步骤:

  1. 从数据中选择k个对象作为初始聚类中心;
  2. 计算每个聚类对象到聚类中心的距离来划分;
  3. 再次计算每个聚类中心
  4. 计算标准测度函数,直到达到最大迭代次数,则停止,否则,继续操作。
  5. 确定最优的聚类中心

K-Means算法应用:

看到这里,你会说,K-Means算法看来很简单,而且好像就是在玩坐标点,没什么真实用处。而且,这个算法缺陷很多,还不如人工呢。是的,前面的例子只是玩二维坐标点,的确没什么意思。但是你想一下下面的几个问题:

1)如果不是二维的,是多维的,如5维的,那么,就只能用计算机来计算了。

2)二维坐标点的X,Y 坐标,其实是一种向量,是一种数学抽象。现实世界中很多属性是可以抽象成向量的,比如,我们的年龄,我们的喜好,我们的商品,等等,能抽象成向量的目的就是可以让计算机知道某两个属性间的距离。如:我们认为,18岁的人离24岁的人的距离要比离12岁的距离要近,鞋子这个商品离衣服这个商品的距离要比电脑要近,等等。

2、实战

from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np

聚类实例

X_train,y_train = make_blobs(n_samples=300,centers=4)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)km = KMeans(4)
km.fit(X_train)y_ = km.predict(X_train)
cluster_centers_=km.cluster_centers_plt.scatter(X_train[:,0],X_train[:,1],c=y_train)plt.scatter(X_train[:,0],X_train[:,1],c=y_)
plt.scatter(cluster_centers_[:,0],cluster_centers_[:,1],c=km.predict(cluster_centers_),cmap='rainbow',s=100)

十三、人脸识别

1、准备工作

1.导入相应的工具包:SVM,GridSearchCV,PCA,matplotlib

2.我们需要相应的数据集

3.还用fetch_lfw_people导入人脸的数据,这个数据包在第一次使用的时候会去下载

4.查看人脸的结构

2、人脸识别

import numpy as np
import matplotlib.pyplot as plt
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split,GridSearchCV
#人脸识别是分类还是回归?分
#人脸自动补全?回归
from sklearn.svm import SVC
from sklearn.decomposition import PCA#min_faces_per_person 把每个人至少有70张图片的数据给筛选出来了
face = datasets.fetch_lfw_people(min_faces_per_person=70,resize=1.0)
face#提取特征值和目标值
data = face.data
target = face.target
target_names = face.target_names
#slice(70, 195, None), slice(78, 172,
face.images.shape
plt.imshow(data[2].reshape(125,94),cmap='gray')#分割数据
X_train,X_test,y_train,y_test = train_test_split(data,target,test_size=0.02)#现在图片的维度是多少 2 维
#对于机器学习来说,图片是多少维的?125 * 125
#维度太高,用PCA降维
#whiten=False  要不要进行标准化的处理
pca = PCA(n_components=150,whiten='True')
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)#SVM
C参数: 惩罚系数,对结果误差的宽容的,C值越高,对于误差的容忍度就越高(过拟合),C值越小误差就越大(欠拟合)
gamma参数:在SVM使用rbf的内核才能使用,表示的是支持向量的数量,gamma越大,支持向量数量越少(决策边境就不准确),gamma越小,支持向量的数量就会越多(效率下降了)
#进行建模  SVM     网格搜索+交叉验证
svc = SVC()
param = {'C':[0.1,0.5,1,1.5,2.0,2.5],'gamma':[0.001,0.003,0.01,0.5]}
#estimator     估算器
#param_grid    要调节的参数,应当是一个字典
gc = GridSearchCV(svc,param,cv=2)
gc.fit(X_train_pca,y_train)#返回最好的参数
gc.best_params_#返回最好的准确率
gc.best_score_#返回最好的模型
svc_best = gc.best_estimator_#评分
svc_best.score(X_train_pca,y_train)y_ = svc_best.predict(X_test_pca)
svc_best.score(X_test_pca,y_test)#将预测的图片全部打印,把真实的目标值和预测的目标值作为标题 26 每行显示5张 2*3
plt.figure(figsize=(5*3,6*5))
for i in range(26):axes = plt.subplot(6,5,i+1)#X_test_pca  X_testaxes.imshow(X_test[i].reshape(125, 94),cmap='gray')#取消刻度轴axes.axis('off')#目标值都是一些数字true_name = target_names[y_test[i]].split(' ')[-1]predict_name = target_names[y_[i]].split(' ')[-1]#设置标题axes.set_title('True:%s\nPredict:%s'%(true_name,predict_name))

3、导出模型

#保存模型
from sklearn.externals import joblib#保存.m的文件
joblib.dump(svc_best,'Bface.m')#加载
model_ = joblib.load('Bface.m')
model_model_.predict(X_test_pca)

如何使用合适的算法

首先我们需要考虑使用机器学习算法的目的。如果想要预测目标变量的值,则可以选择监督学习算法,否则可以选择无监督学习算法。确定选择监督学习算法之后,需要进一步确定目标变量的的类型,如果目标变量是离散型,如是/否,1/2/3,等等,则可以选择分类器算法;如果目标变量是连续型的数值,如0.0~100.00、-999~999等,则需要选择回归算法
如果不想预测目标变量的值,则可以选择无监督学习。进一步分析是否需要将数据划分为离散的组。如果这是唯一的要求,则使用聚类算法;如果还需要估计数据与每个分组的相似的程度,则需要使用密度估计算法

Published by

风君子

独自遨游何稽首 揭天掀地慰生平