Python之NumPy

wuchangjian2021-11-03 00:56:06编程学习

文章目录

    • 1.概述
      • 1.1背景介绍
      • 1.2NumPy介绍
    • 2.NumPy数组对象
      • 2.1NumPy创建数组
        • 2.1.1使用NumPy的array()创建
        • 2.1.2使用NumPy其他函数
      • 2.2NumPy查看数组属性
    • 3.NumPy数组操作
      • 3.1NumPy数组切片和索引
        • 3.1.1一维数组切片和索引
        • 3.1.2多维数组切片和索引
        • 3.1.3神奇索引
        • 3.1.4布尔索引
      • 3.2NumPy数组变形
      • 3.2NumPy数组基本运算
        • 3.2.1数组的+、-、\*、/
        • 3.2.2聚合运算
        • 3.2.3矩阵运算

由此便进入到数据可视化的学习

数据分析一般流程:数据读写–>数据的处理计算–>数据的分析建模–>数据可视化

用Python进行数据分析工具有三:

  1. NumPy:多维数组/矩阵基础包,是很多其他包(如Pandas)的基石
  2. Pandas:基于NumPy的数据分析,支持Series、DataFrame等,功能强大
  3. Matplotlib:用于快速生成2D图像

1.概述

1.1背景介绍

现实世界中很多实际问题都可以抽象成n维数组,比如:一张黑白照片,是由 长度*宽度*单个像素的灰度 三维数组组成;一张彩色照片,也可以抽象成 长度*宽度*单个像素上(R*G*B) 这样更多维数组组成;还有音频等等,普通的表格数据记录更是如此。所以NumPy应运而生。

1.2NumPy介绍

Numpy是用于数据科学计算的基础模块,是Python的一个开源数值计算扩充程序库。不但支持大量的维度数组和矩阵运算,还能被用作高效的多维数据容器,可用于存储和处理大型矩阵。也有助于其他高效的数据处理工具的使用。

NumPy提供了两种基本对象,以弥补传统Python用list(列表)保存值而存在浪费CPU等诸多问题:

  • ndarray:是存储单一数据类型的多维数组
  • ufunc:一种能够对数据进行处理的函数

2.NumPy数组对象

注:下文np是import numpy as np引入的numpy的别名,正常使用可以直接使用numpy

2.1NumPy创建数组

2.1.1使用NumPy的array()创建

  1. 一维数组

    a = np.array([1,2,3])

  2. 二维数组

    a = np.array([1,2,3],[4,5,6],[7,8,9])

  3. 多维数组

    a = np.array([[[1,2], [3,4]],[[5,6],[7,8]]])

    等等,三维数组如上,即在二维之上在加一个维度,达成2*2*2。同理,三维数组的3*3*3如下:

    import numpy as np
    a=np.array([[[1,2,3],[1,2,3],[1,2,3]],
               [[4,5,6],[4,5,6],[4,5,6]],
               [[7,8,9],[7,8,9],[7,8,9]]])
    #输出如下
    # [[[1 2 3]
    # [1 2 3]
    # [1 2 3]]
    
    # [[4 5 6]
    #  [4 5 6]
    #  [4 5 6]]
    
    # [[7 8 9]
    #  [7 8 9]
    #  [7 8 9]]]
    

    更多维数组同理。

    注意:array数组样式为array([]),无论里面有多少[],最外一层要用[]套起来,要确保括号的数量对应的起来。


2.1.2使用NumPy其他函数

  1. 使用arange()函数

    格式为:np.arange(start, stop, step, dtype)

    类似于range,由前两个参数指定上界和下界,第三个参数指定步长,并且不同于range,步长可以是浮点数

    a = np.arange(1,5)得到array([1,2,3,4])

    b = np.arange(1,5,0.5)得到array([1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5])

    arange()的reshape()函数可以指定矩阵的维度

    格式为:reshape(参数1, 参数2, 参数3, ...)

    一个参数代表一个维度的长度,比如二维2*4,就(2,4);三维3*3*6,就(3,3,6)

    c = np.arange(1,5).reshape(2,2)得到array([1,2],[3,4])

  2. 使用linspace()函数

    格式为:linspace(start, stop, num )

    从start开始,到stop结束(包括stop),按等差数列生成数组,num为数组元素个数,默认50个

    a = np.linspace(1, 10, 5)得到array([1. 0, 3.25, 5.5, 7.75, 10.0])

  3. 其他的特殊函数(zeros(),ones(),ones_like(),random(),full())

    a = np.ones(3)得到array([1,1,1])即3个1

    b = np.zeros(4)得到array([0,0,0,0])即4个0

    c = np.zeros(2,2)得到array([0,0], [0,0])

    其他类似

    还有d = full(shape=(3,2), fill_value=123

    得到array([123,123,123], [123,123,123])

    等等等等,略了略了

总结常用函数如下:

image-20211031133036232

2.2NumPy查看数组属性

NumPy的主要对象是同质多维数组/矩阵

同质即元素类型都相同,其中维度称作轴axis,轴的数目称为rank。

axis 0 通常指行;axis 1通常指列

属性(方法)说明
ndim返回int。数组的维数。
shape返回tuple。数组的尺寸,例n*m的数组,则为(n,m)。
size返回int。数组元素总数。
dtype返回data-type。数组中元素的类型。
itemsize返回int。数组每个元素的大小(以字节为单位)。

实例:

import numpy as np
arr = np.arange(1,13).reshape(3,4)
# [[1 2 3 4] [5 6 7 8] [9 10 11 12]]
print(arr.shape) # (3,4),形状
print(arr.ndim) # 2,维度
print(arr.dtype) # int32,元素类型
print(arr.size) # 12,元素个数

注意:与函数不同,最后不需要(),没有参数


3.NumPy数组操作

3.1NumPy数组切片和索引

注意:NumPy数组用切片得到的子矩阵(数组)不同于Python中普通列表的切片,会修改原有数据值。若想不影响,可以先做一个副本,可以使用copy()函数。

3.1.1一维数组切片和索引

与列表切片相同

数组索引是从0开始,且切片[start : end],从start开始到end-1结束

arr = np.arrange(3) # [0 1 2]
print(arr[0:2]) # [0 1]
print(arr[-1]) # 2
print(arr[-1:]) # [2]
print(arr[1:]) # [1 2]

3.1.2多维数组切片和索引

以二维数组为例:

格式为arr[x_start:x_end,y_start:y_end]

可以看作有两个切片(从start到end-1)组成的,中间用逗号隔开。前一个是在行的切片,取的是行数;后一个是在列的切片,取的是列数。

实例如下,比如第一个例子,“:2”取0、1即前两行,“1:”取1、2即后两行,交叉形成的即为取出的切片。

image-20211101233629606

多维数组同理,几维即采用几层切片,中间用逗号隔开即可

3.1.3神奇索引

前面两个都是普通的索引,一般只能取出连续分布或因设置步长而产生的有规律的元素。但**神奇索引(整数索引)**可以一次性访问数组中多个没有任何规律的元素。

神奇索引又与普通索引不同,它总是将数据复制到一个新的数组,不会影响原有数据

  1. 一维数组

    用索引组成数组,得到索引数组,使用索引数组一次性调用多个数组元素

    索引数组也是数组,两边要有中括号“[]”

    arr = np.array([10,11,12,13,14,15,16])
    f_arr = arr[[0,3,5]] # [0,3,5]即为索引数组,得到f_arr=[10,13,15]
    
  2. 多维数组

    与前面多维数组的切片可以类似地理解,用逗号隔开,使用多层索引数组进行定位

    以二维数组为例,前面一个为行索引,后面一个为列索引,只写一个只单独调用行或、列,当两者同在,即可根据行和列取具体的值

    arr = np.array([[10,11,12,13],
            [20,21,22,23],
            [30,31,32,33]])
    arr_1 = arr[[0,2]] 
    # arr_1 = ([[10,11,12,13],
    #			[30,31,32,33]]),只有行索引,则取的是[0]行和[2]行
    arr_2 = arr[[0,2],[1,2]]
    # arr_2 = ([11,32]),分别取的是[0][1]、[2][2]
    

    三维及以上同理

3.1.4布尔索引

使用比较运算符作索引,比如在一堆整数的数组中,你想找到等于6或者比6大的数,那么就可以分别使用“==6”和“>6”来创建布尔数组

注意:一维数组的长度必须和索引数组的长度一致

import numpy as np
arr = np.array([2,3,4,5,6,7,8,9])
arr_1 = (arr==6)
# 通过比较运算符创建布尔数组:[False,False,False,False,True,False,False,False]
arr[arr_1] # 通过布尔索引输出[6]

arr_2 = (arr>6)
# 通过比较运算符创建布尔数组:[False,False,False,False,False,True,True,True]
arr[arr_2] # 通过布尔索引输出[7 8 9]

arr_3 = np.array([True,True,True,False,False,True,True,True])
# 直接创建一个布尔数组
arr[arr_3] # [2 3 4 7 8 9]

对于多维数组,同其他索引,使用多个一维布尔索引来定位


3.2NumPy数组变形

使用**reshape()**函数,设置和改变数组形状

使用**ravel()**函数,返回原始展平的数组视图,对原数组本身是没有影响的

使用**flatten()函数,得到一个展平的数组,与上一个不同,此函数会分配新内存,完成原数组到新数组的拷贝,则原数组数据不会发生改变。参数为’F’**时,纵向展平;默认横向展平

相比于ravel()函数,要达到展平数组的目的,一般还是使用flatten()函数

arr = np.array([0,1,2,3,4,5])
arr.reshape(3,2) 
# [ [0 1 2] 
#   [3 4 5] ]
arr.ravel() # [0 1 2 3 4 5]
arr.flatten() # [0 1 2 3 4 5]
arr.flatten('F') # [0 3 1 4 2 5]

使用**hstack()**函数实现数组横向组合:np.hstack((arr1,arr2))

使用**vstack()**函数实现数组纵向组合:np.vstack((arr1,arr2))

使用concatenate()函数实现数组横向组合,令参数axis=1np.concatenate((arr1,arr2),axis=1))

使用concatenate()函数实现数组纵向组合,令参数axis=0np.concatenate((arr1,arr2),axis=0))

import numpy as np
arr1 = np.array([[10, 11, 12], [13, 14, 15]])
arr2 = np.array([[20, 21, 22], [23, 24, 25]])

arr_1 = np.hstack((arr1, arr2))
# [[10 11 12 20 21 22]
#  [13 14 15 23 24 25]]
arr_2 = np.vstack((arr1, arr2))
# [[10 11 12]
#  [13 14 15]
#  [20 21 22]
#  [23 24 25]]
arr_3 = np.concatenate((arr1, arr2), axis=1) # 同arr_1
arr_4 = np.concatenate((arr1, arr2), axis=0) # 同arr_2

使用**hsplit()**函数实现数组横向分割:np.hsplit(arr, 2)

使用**vsplit()**函数实现数组纵向分割: np.vsplit(arr, 2)

使用split()函数实现数组横向分割,令参数axis=1np.split(arr, 2, axis=1)

使用split()函数实现数组纵向分割,令参数axis=0np.split(arr, 2, axis=0)可以将数组分成相同大小的子数组

import numpy as np
arr = np.arange(16).reshape(4, 4)

arr_1 = np.hsplit(arr, 2)
# [array([[ 0,  1],
#        [ 4,  5],
#        [ 8,  9],
#        [12, 13]]), 
#  array([[ 2,  3],
#        [ 6,  7],
#        [10, 11],
#        [14, 15]])]
arr_2 = np.vsplit(arr, 2)
# [array([[0, 1, 2, 3],
#        [4, 5, 6, 7]]), 
#  array([[ 8,  9, 10, 11],
#        [12, 13, 14, 15]])]
arr_3 = np.split(arr, 2, axis=1) # 同arr_1
arr_4 = np.split(arr, 2, axis=0) # 同arr_2

注意:遇到无法合并的、无法分割的,程序运行时会报错


3.2NumPy数组基本运算

3.2.1数组的+、-、*、/

数组的“+、-、*、/”均是对数组内部元素的操作

一维数组:要求元素数目能够一一对应,则一一对应计算,否则会报错

import numpy as np
arr1 = np.array([2, 1])
arr2 = np.array([4, 5])

print(arr1+arr2) # [6 6]
print(arr1-arr2) # [-2 -4]
print(arr1*arr2) # [8 5]
print(arr1/arr2) # [0.5 0.2] 除法会自动转浮点型,没有小数也会显示小数点

多维数组

若数目可以对上,则同一维数组,一一对应计算;

若对不上,另一数组为一维数组,则触发广播机制,使每个或每组元素都进行同一计算,如下例;

若都是多维数组,对不上,触发不了广播机制,则报错。

import numpy as np
arr1 = np.array([[1, 2], [3, 4], [5, 6]])
arr2 = np.array([1, 2])
arr3 = np.array([1, 2], [3, 4])

print(arr1+arr2)
# [[2 4]
#  [4 6]
#  [6 8]]
print(arr1/arr2)
# [[1. 1.]
#  [3. 2.]
#  [5. 3.]]
# 其他类似
print(arr1*arr3) # 报错

3.2.2聚合运算

所谓聚合,就是把一组值变为一个值

NumPy中的聚合函数对单个数组进行操作,得到一个值,NumPy常用聚合函数如下:

函数说明
sum(arr)计算数组arr的和
mean(arr)计算数组arr均值
std(arr)计算数组arr标准差
var(arr)计算数组arr方差
min(arr)计算数组arr最小值
max(arr)计算数组arr最大值
argmin(arr)返回数组arr最小元素的索引
argmax(arr)返回数组arr最大元素的索引
cumsum(arr)计算轴向展平数组元素累加和,返回由中间结果组成的数组
cumprod(arr)计算轴向展平数组元素累乘积,返回由中间结果组成的数组
import numpy as np
arr = np.array([[1,2],[3,4]])
print(np.sum(arr)) # 10

3.2.3矩阵运算

矩阵点乘:对于得到的数组来说,其元素为第一数组同一行上每一元素与第二数组同一列上每一元素相乘之后再求和所得,第一数组与第二数组互相操作的行与列交叉点就是所得元素

这里说的是线性代数里的矩阵点乘

普通元素间乘法使用np.multiply(arr1,arr2)或直接arr1*arr2

点乘则使用np.dot(arr1,arr2)arr1.dot(arr2)

import numpy
a = numpy.array([[1,2],
                 [3,4]])
b = numpy.array([[5,6],
                 [7,8]])
a*b
# array([[5, 12],
#        [21, 32]])
a.dot(b)
# array([[19, 22],   
#        [43, 50]])
numpy.dot(a,b)
# array([[19, 22],
#        [43, 50]])
numpy.dot(b,a)
# array([[23, 34],
#        [31, 46]])

相关文章

Cesium 3DTiles类关系说明

1.Cesium3DTileset :瓦片集 2.Cesium3DTil...

21天好习惯第一期-17

怎么获得一个数的百位,十位和个位 百位数:num/100 ...

OpenCV学习(11)-直方图正规化

# -*- coding: utf-8 -*- import sys import cv...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。