NumPy 快速入门:数组对象,数组属性,花式索引等基础介绍

   日期:2020-07-12     浏览:284    评论:0    
核心提示:NumPy 快速入门:数组对象,数组属性,花式索引等基础介绍1、NumPy 简介:2、ndarray 数组对象:3、创建数组:4、数组的数据类型:5、数组的结构:6、数组的简单计算:7、数组切片与索引:8、数组的组合与切割:1、NumPy 简介:NumPy (Numerical Python的简称)是高性能科学计算和数据分析的基础包,是想利用 Python 进行数据分析人士必须了解的模块之一。由于各种原因 NumPy 模块并不是 Python 的标准模块,故需安装使用:pip install n

NumPy 快速入门:数组对象,数组属性,花式索引等基础介绍

        • 1、NumPy 简介:
        • 2、ndarray 数组对象:
        • 3、创建数组:
        • 4、数组的数据类型:
        • 5、数组的结构:
        • 6、数组的简单计算:
        • 7、数组切片与索引:
        • 8、数组的组合与切割:
        • 9、数组的属性:
        • 结尾:

1、NumPy 简介:

NumPy (Numerical Python的简称)是高性能科学计算和数据分析的基础包,是想利用 Python 进行数据分析人士必须了解的模块之一。

由于各种原因 NumPy 模块并不是 Python 的标准模块,故需安装使用:

pip install numpy

导入 NumPy 模块时通常约定写成:

import numpy as np

numpy 主要功能:

  1. 提供 ndarray 对象:具有矢量算数运算和复杂广播能力的多维数组;
  2. 提供了许多可对数组对象直接运算的标准数学函数,而无需编写循环;
  3. 提供了用于读写磁盘数据的工具及用于操作内存映射文件的工具;
  4. 提供了线性代数、随机生成及傅里叶变换功能;
  5. 用于集成由 C 、C++、Fortran 等语言编写的代码的工具。

2、ndarray 数组对象:

ndarray 是指 NumPy 中的N维数组对象,是一个快速而灵活地大数据集容器。

3、创建数组:

array 函数: 可接收一切序列对象(包括其他数组对象),然后产生一个新的 NumPy 数组。

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
参数 含义
object 数组或嵌套的数列
dtype 数组元素的数据类型,可选
copy 对象是否需要复制,可选
order 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)
subok 默认返回一个与基类类型一致的数组
ndmin 指定生成数组的最小维度

简单示例:

import numpy as np  # 导入模块,后面示例不再写

data = [6,7.5,8,0,1]
arr1 = np.array(data)
print(arr1)  # [6. 7.5 8. 0. 1. ]

接收一个嵌套序列:

data2 = [[1,2,3,4],[5,6,7,8]]
arr2 = np.array(data2)
print(arr2)
''' [[1 2 3 4] [5 6 7 8]] '''

解析: 除非设置数据类型(数据类型稍后会详细介绍),或者 array 函数会根据传入的序列选择适合的数据类型。

如,在上面 arr1 中,传入的列表中有 7.5 浮点数,所以创建的 arr1 数组类型为浮点型。

查看创建的数组数据类型:

print(arr1.dtype)  # float64
print(arr2.dtype)  # int32 或 int64 ,和安装的 Python 版本有关

其他创建数组的方法:


zeros 函数: 创建全 0 数组

# 创建一维数组
print(np.zeros(10))  # [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
# 创建多维数组
print(np.zeros((3,6)))  
''' [[0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0.]] '''

empty 函数:

print(np.empty((2,3,2)))
''' [[[8.74e-322 0.00e+000] [0.00e+000 0.00e+000] [0.00e+000 0.00e+000]] [[0.00e+000 0.00e+000] [0.00e+000 0.00e+000] [0.00e+000 0.00e+000]]] '''

arange 函数: 是 Python 内置函数 range 的数组版

# arange 函数
print(np.arange(15))  
# [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]

eye 函数: 创建一个单位矩阵

print(np.eye(3,3))
''' [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]] '''

4、数组的数据类型:

NumPy 的一个数组对象里所有的数据都是同质的,即数组内 数据类型一致



设置、查看数组对象数据类型:

arr3 = np.array([1,2,3],dtype=np.float)
arr4 = np.array([1,2,3],dtype=np.int)
print(arr3.dtype,arr4.dtype) 
# 打印结果
# float64 int32

转换数组数据类型:

arr5 = np.array([1,2,3,4,5])
print(arr5.dtype)  # int32
float_arr5 = arr5.astype(np.float)
print(float_arr5.dtype)  # float64

注:astype 会创建一个新的数组对象

自定义数据类型:

NumPy 也提供了自定义数组对象的数据类型方法。自定义数据类型是一种异构数据类型,可以当做记录一行数据的结构。
如:创建一个存储商店库存信息的数据类型,该库存信息有:商品名称、库存数量、商品价格。

# 创建数据类型
my_type = np.dtype([('name',np.str,40),('numitems',np.int),('price',np.float)])
print(my_type)  # [('name', '<U40'), ('numitems', '<i4'), ('price', '<f8')]

# 创建数组
my_array = np.array([('DVD',42,3.14),('Butter',13,2.72)],dtype= my_type)

# 查看数组数据类型
print(my_array.dtype)
# [('name', '<U40'), ('numitems', '<i4'), ('price', '<f8')]

5、数组的结构:

数组对象的结构指的是数组的维度、轴的概念。

查看数组结构:

b = np.arange(24)
print(b.shape) # (24,)

改变数组结构:

reshape 方法:生成一个新的数组对象。

c = b.reshape(2,3,4)  # 改变数组维度
print(c)
''' [[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[12 13 14 15] [16 17 18 19] [20 21 22 23]]] '''
print(c.shape)  # (2, 3, 4)

resize 方法: 原位改变数组结构。

g = np.arange(6)
print(g.shape)  # (6,)
g.resize(2,3)  # 会在原位修改数组结构
print(g)
''' [[0 1 2] [3 4 5]] '''
print(g.shape)  # (2, 3)

注:reshape 方法和 resize 都可改变数组维度,但是 reshape 改变数组结构时,会产生一个新的数组对象;而 resize 则是直接修改原数组的维度。

数组的转置:

arr3 = np.arange(6).reshape(2,3)
print(arr3)
''' [[0 1 2] [3 4 5]] '''
arr4 = arr3.transpose()
print(arr4)
''' [[0 3] [1 4] [2 5]] '''

6、数组的简单计算:

NumPy 数组对象与 Python 原生序列最显著的区别之一就是在对序列中的数据执行批量运算,数组对象进行批量运算时,不需要编写循环可直接进行计算,及数组的矢量化

这样也令其在大量数据计算时,运行效率明显提升。

数组与标量之间的运算:

arr6 = np.array([[1,2,3],[4,5,6]],dtype=float)
print(arr6)
''' [[1. 2. 3.] [4. 5. 6.]] '''
# 加法
print(arr6 + 2)
''' [[3. 4. 5.] [6. 7. 8.]] '''

# 乘法:
print(arr6*0.5)
''' [[0.5 1. 1.5] [2. 2.5 3. ]] '''

数组与数组之间的运算:

大小相同的数组之间的任何算术运算都会讲运算应用到元素级:

# 减法
print(arr6-arr6)
''' [[0. 0. 0.] [0. 0. 0.]] '''
# 乘法
print(arr6*arr6)
''' [[ 1. 4. 9.] [16. 25. 36.]] '''

7、数组切片与索引:

一维数组的切片与索引:

arr7 = np.arange(10)
print(arr7)  # [0 1 2 3 4 5 6 7 8 9]
print(arr7[5]) # 5
print(arr7[5:8])  # [5 6 7]

以上操作的结果和 Python 列表切片索引操作现象一致。

切片赋值操作:

对一个切片对象赋值:

arr7[0] = 10
print(arr7)
# [10 1 2 3 4 5 6 7 8 9]

对切片组赋值:

arr7[5:8] = 12
print(arr7)
# [10 1 2 3 4 12 12 12 8 9]

注:当将一个标量值给一个切片时,该值会自动传播到整个选取,这是和Python列表切片最重要的区别 !

arr_slice = arr7[5:8]
arr_slice[1] = 12345
print(arr7)  
# [ 0 1 2 3 4 12 12345 12 8 9]

arr_slice[:] = 64
print(arr7) # [ 0 1 2 3 4 64 64 64 8 9]

这是因为NumPy的设计目的是处理大数据,如要将数据多次复制(创建新的对象),会产生非常大的性能和内存问题。

高维数组的索引及切片:

二维数组:

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

# 以下两种方式效果一致
print(arr2d[0][2]) # 3
print(arr2d[0,2])  # 3

三维数组:

arr3d = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
print(arr3d)
print(arr3d.shape)  # (2, 2, 3)
''' 一个 2 x 2 x 3 数组 [[[ 1 2 3] [ 4 5 6]] [[ 7 8 9] [10 11 12]]] '''

print(arr3d[0])
''' [[1 2 3] [4 5 6]] '''

标量值和数组都可被赋值给切片对象,如:

old_value = arr3d[0].copy() # 复制数组对象
arr3d[0] = 42
print(arr3d)
''' [[[42 42 42] [42 42 42]] [[ 7 8 9] [10 11 12]]] '''
arr3d[0] = old_value
print(arr3d)
''' [[[ 1 2 3] [ 4 5 6]] [[ 7 8 9] [10 11 12]]] '''
print(arr3d[1,0]) # [7 8 9]

布尔值切片:

这也是和 Python 原序列切片很大的不同之处,如:

先建立一个布尔序列:

names = np.array(['bob','joe','will','bob','will','joe','joe'])
# 数组的比较运算也是矢量化的,会产生一个布尔型数组
print(names == 'bob') 
# [ True False False True False False False]

用布尔序列对数组进行切片操作:

data = np.random.rand(7,4) # 生成一些正态分布的随机数据
print(data)
''' [[0.64831166 0.53764074 0.05100258 0.86194823] [0.75817438 0.68161727 0.23507438 0.06506362] [0.31393836 0.3548072 0.52740244 0.07263428] [0.03731951 0.3401235 0.25695301 0.08632226] [0.84201383 0.54950122 0.38923988 0.77718169] [0.14664734 0.59178141 0.62562549 0.2584329 ] [0.03764809 0.1270825 0.39032711 0.09212854]] '''
# 布尔型数组可用于数组索引
print(data[names == 'bob'])
''' [[0.64831166 0.53764074 0.05100258 0.86194823] [0.03731951 0.3401235 0.25695301 0.08632226]] '''

注:布尔型数组的长度必须和被索引的轴长度一致。

布尔型数组也可以跟切片、整数混合使用:

print(data[names == 'bob', 2:])
''' [[0.05100258 0.86194823] [0.25695301 0.08632226]] '''
print(data[names == 'bob',3])
''' [0.86194823 0.08632226] '''

注意以下的一种用法:

# 将data中的所有小于0.5的值设置为0
data[data<0.5] = 0
print(data)
''' [[0.64831166 0.53764074 0. 0.86194823] [0.75817438 0.68161727 0. 0. ] [0. 0. 0.52740244 0. ] [0. 0. 0. 0. ] [0.84201383 0.54950122 0. 0.77718169] [0. 0.59178141 0.62562549 0. ] [0. 0. 0. 0. ]] '''

这在实现筛选数据功能上非常方便!

花式索引:

花式索引:NumPy术语,指利用整数数组进行索引,如:

arr9 = np.empty((8,4))
for i in range(8):
    arr9[i] = i

print(arr9)
''' [[0. 0. 0. 0.] [1. 1. 1. 1.] [2. 2. 2. 2.] [3. 3. 3. 3.] [4. 4. 4. 4.] [5. 5. 5. 5.] [6. 6. 6. 6.] [7. 7. 7. 7.]] '''

print(arr9[[4,3,0,6]])
''' [[4. 4. 4. 4.] [3. 3. 3. 3.] [0. 0. 0. 0.] [6. 6. 6. 6.]] '''

使用负数会从末尾开始选取行:

print(arr9[[-1,-3,-7]])
[[7. 7. 7. 7.]
 [5. 5. 5. 5.]
 [1. 1. 1. 1.]]
'''

多个花式索引结合:

arr10 = np.arange(32).reshape((8,4))
print(arr10)
''' [[ 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]] '''

print(arr10[[1,5,7,2],[0,3,1,2]]) # [ 4 23 29 10]

print(arr10[[1,5,7,2]][:,[0,3,1,2]])
''' [[ 4 7 5 6] [20 23 21 22] [28 31 29 30] [ 8 11 9 10]] '''

注:花式索引和切片不一样,它总是将数据复制到新数组中。

8、数组的组合与切割:

水平组合:

a1 = np.arange(9).reshape(3,3)
a2 = a1 * 2
a3 = np.hstack((a1,a2))
print(a3)
''' [[ 0 1 2 0 2 4] [ 3 4 5 6 8 10] [ 6 7 8 12 14 16]] '''

使用 concatenate 函数进行水平组合

a4 = np.concatenate((a1,a2),axis=1)
print(a4)
''' [[ 0 1 2 0 2 4] [ 3 4 5 6 8 10] [ 6 7 8 12 14 16]] '''

垂直组合:

# 垂直组合
a5 = np.vstack((a1,a2))
print(a5)
''' [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 0 2 4] [ 6 8 10] [12 14 16]] '''
# 使用 concatenate 函数进行垂直组合
a6 = np.concatenate((a1,a2),axis=0)
print(a6)
''' [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 0 2 4] [ 6 8 10] [12 14 16]] '''

深度组合:

a7 = np.dstack((a1,a2))
print(a7)
''' [[[ 0 0] [ 1 2] [ 2 4]] [[ 3 6] [ 4 8] [ 5 10]] [[ 6 12] [ 7 14] [ 8 16]]] '''

注:深度组合,改变了数组的维度。

print(a1.shape,a2.shape,a7.shape)  
# (3, 3) (3, 3) (3, 3, 2)

列组合:

# 列组合
b1 = np.arange(2)
b2 = b1 * 2
b3 = np.column_stack((b1,b2))
print(b3)
''' [[0 0] [1 2]] '''
# 注意一维数组的列组合与水平组合的区别
b4 = np.hstack((b1,b2))
print(b4)
''' [0 1 0 2] '''
# 对于二维数组,列组合与水平组合效果相同
b5 = np.column_stack((a1,a2))
print(b5)
''' [[ 0 1 2 0 2 4] [ 3 4 5 6 8 10] [ 6 7 8 12 14 16]] '''

注:对于二维数组,列组合与水平组合效果相同。

行组合:

# 行组合
b6 = np.row_stack((b1,b2))
print(b6)
''' [[0 1] [0 2]] '''
# 同样需注意一维数组的行组合与垂直组合的区别
# 对于二维数组,行组合与垂直组合效果一致
b6 = np.row_stack((a1,a2))
print(b6)
''' [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 0 2 4] [ 6 8 10] [12 14 16]] '''

数组分割:

对应数组的组合,也包括数组的水平分割、垂直分割、深度分割。

c1 = np.arange(9).reshape(3,3)
print(c1)
''' [[0 1 2] [3 4 5] [6 7 8]] '''

# 水平分割
c2 = np.hsplit(c1,3)
print(c2)
''' [array([[0], [3], [6]]), array([[1], [4], [7]]), array([[2], [5], [8]])] '''
print(type(c2)) # 获得一个包含数组的列表
# <class 'list'>
# split 函数进行水平分割
c3 = np.split(c1,3,axis=1)
print(c3)
''' [array([[0], [3], [6]]), array([[1], [4], [7]]), array([[2], [5], [8]])] '''

# 垂直分割
c4 = np.vsplit(c1,3)
print(c4)
''' [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])] '''
# 同样也可以用 split 函数实现垂直分割
c5 = np.split(c1,3,axis=0)
print(c5)  # [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]

# 深度分割
d1 = np.arange(27).reshape(3,3,3)
print(d1)
''' [[[ 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]]] '''
print(d1.shape)  # (3, 3, 3)

d2 = np.dsplit(d1,3)
print(d2)
''' [array([[[ 0], [ 3], [ 6]], [[ 9], [12], [15]], [[18], [21], [24]]]), array([[[ 1], [ 4], [ 7]], [[10], [13], [16]], [[19], [22], [25]]]), array([[[ 2], [ 5], [ 8]], [[11], [14], [17]], [[20], [23], [26]]])] '''
for d_ in d2:
    print(d_.shape)

# 深度分割将一个 3x3x3 数组切割为一个包含3个 3x3x1 数组的列表
''' (3, 3, 1) (3, 3, 1) (3, 3, 1) '''

9、数组的属性:

ndim 获取数组维度或轴个数:

e1 = np.arange(24).reshape(2,12)
print(e1)
''' [[ 0 1 2 3 4 5 6 7 8 9 10 11] [12 13 14 15 16 17 18 19 20 21 22 23]] '''
# ndim 获取数组维度或轴个数
print(e1.ndim)  # 2

size 获取数组元素总个数:

print(e1.size)  # 24

itemsize 获取数组中元素在内存中所占字节数:

print(e1.itemsize)  # 4

nbytes 获取数组对象所占储存空间:

print(e1.nbytes)  # 96

注:总是等于 itemsize 值与 size 值的乘积。

flat 获取数组对象的扁平迭代器(flatiter):

e2 = np.arange(9).reshape(3,3)
print(e2)
''' [[0 1 2] [3 4 5] [6 7 8]] '''
e_flat = e2.flat # 这是获取 flatiter 对象的唯一方式
print(e_flat)  # <numpy.flatiter object at 0x000000000A1306C0>

for item in e_flat:
    print(item,end=',')
# 0,1,2,3,4,5,6,7,8,

结尾:

以上就是本篇博客全部内容,感谢阅读。

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服