Python中使用NumPy进行数据处理方式

 更新时间:2024年02月27日 08:38:19   作者:Vic·Tory  
这篇文章主要介绍了Python中使用NumPy进行数据处理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Numpy是一个常用的Python科学技术库,通过它可以快速对数组进行操作,包括形状操作、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等。许多Python库和科学计算的软件包都使用Numpy数组作为操作对象,或者将传入的Python数组转化为Numpy数组,因此在Python中操作数据离不开Numpy。

Numpy的核心是ndarray对象,由Python的n维数组封装而来,但通过C语言预编译相关的数组操作,因此比原生Python具有更高的执行效率,但仍然使用Python语言编码,这样就同时具有简洁的代码和高效的运行速度。ndarry与数组有些区别值得注意,numpy数组中的元素都具有相同的类型,并且在创建时就确定了固定的大小,这与Python数组对象可以动态增长不同。

1、数组属性

Numpy对象的形式是同构多维数组,数组的维度称为轴(axis),每个维度上元素的个数称为轴的长度。例如下面是一个2×3的二维数组arr,第一轴长度为3,第二轴长度为2

    arr = [[ 1., 0., 0.],
           [ 0., 1., 2.]]

arr数组对象常用的属性如下:

    # 数组轴的个数
    arr.ndim
    # 数组维度及长度,例如2×3的数组其shape为(2, 3)
    arr.shape
    # 数组元素的总个数
    arr.size
    # 数组中元素的数据类型
    arr.dtype
    # 数组中元素所占字节数
    arr.itemsize

2、创建数组

可以通过array()方法包裹普通python数组将其转化为numpy数组,通过dtype=规定元素的数据类型。数组可以是二维等高维数组,也可以是元组的形式。

填充指定大小的数组可以使用函数zeros(),将元素都填充为0,或者ones()将元素填充为1,empty()将元素填充为随机数

np.random模块用于产生随机数,rand()创建[0,1)内指定维度的随机数组,uniform()randint()在指定范围内生成浮点数/整数。有时候我们希望产生的相同的随机数,或者产生的随机数可以再现,可以通过np.random.seed()指定随机数种子,当种子相同时产生的随机数相同。

arange(a,b,c)函数用于从a到b每隔c长度生成一个数组元素。linspace(a,b,c)函数用于在a到b之间生成c个数组元素

	import numpy as np

    # 普通数组转化为numpy数组
    a1 = np.array([2, 3, 4], dtype=float)
    print(a1)                                    
    # 将元组数组转化为二维numpy数组
    a2 = np.array([(1, 2, 3), (3, 4, 5)])
    print(a2)
    # 将3×3的数组用1填充
    a3 = np.ones((3, 3))
    print(a3)
    # 从1到10,每隔2生成一个元素
    a4 = np.arange(1, 10, 2)
    print(a4)
    # 在1到12之间生成4个元素
    a5 = np.linspace(1, 12, 4, dtype=int)
    print(a5)
	# 生成指定维度的随机数组
	print(np.random.rand(1, 5))
	# 在指定区间生成随机浮点数
	print(np.random.uniform(low=1, high=2, size=5))
	# 在指定区间生成随机浮点数
	print(np.random.randint(low=1, high=10, size=5))
	# 使用相同的种子产生随机数
    np.random.seed(666)
	print(np.random.rand(5))
	np.random.seed(666)  # 每次产生前都要设置
	print(np.random.rand(5)) 
    '''
    普通数组转化为numpy对象:
    [2. 3. 4.]
    元组数组:
    [[1 2 3]
     [3 4 5]]
    用1填充数组:
    [[1. 1. 1.]
     [1. 1. 1.]
     [1. 1. 1.]]
    从1到10每隔2生成一个元素:
    [1 3 5 7 9]
    在1到12之间生成4个元素:
    [ 1  4  8 12]
    生成(1, 5)浮点数组
    [[0.73483009 0.42395071 0.03067476 0.87905934 0.3825438 ]]
    在[1,2)产生5个随机浮点数数
	[1.73563967 1.20877954 1.59162307 1.1021683  1.29736842]
	在[1,10)产生5个随机整数
	[6 5 3 6 8]
	相同的随机数
	[0.70043712 0.84418664 0.67651434 0.72785806 0.95145796]
	[0.70043712 0.84418664 0.67651434 0.72785806 0.95145796]
    '''

3、数组操作

3.1 数组运算

算术运算符可以直接运用在矩阵上,其结果是将运算应用到每个元素上,例如矩阵A*B就是每个元素对应相乘,矩阵的乘法运算使用的是@符号

    A = np.array([[1, 1],
                  [0, 1]])
    B = np.array([[2, 0],
                  [3, 4]])
    print(A * B)
    print(A @ B)
     
    '''
    矩阵元素对应相乘:
    [[2 0]
     [0 4]]
    矩阵的乘法:
    [[5 4]
     [3 4]]
    '''

numpy中有些函数应用于整个数组,例如求和sum、最大值max、最小值min。如果在这些参数中指定了某个轴,则应用于指定轴。

还有一些函数应用于数组中的具体元素,例如求sincosexp、开方sqrt等,这些函数叫做通函数(ufunc)

    a = np.array([[0, 1, 2, 3],
                  [4, 5, 6, 7],
                  [8, 9, 10, 11]])
    print(a.max())  # 求整体的最大值,结果为11
    print(a.sum(axis=0))  # 求每一列的和,结果为:[12 15 18 21]
    print(np.sqrt(a))   # 数组每个元素求开方

3.2 选取元素

numpy中的数组同python中的list一样可以进行索引、切片和迭代操作。a[x]代表访问数组a下标为x的元素,a[x:y]代表访问数组从x到y的元素,如果省略x代表从头开始,省略y代表直到结尾。a[x:y:a]代表从x到y每隔a个元素取一个值,如果a为负数,代表逆序取值。

    a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    print(a[1:3])  # 输出下标为1到3的元素:[1 2]
    print(a[::-2])  # 逆序每隔两个元素选一个值:[9 7 5 3 1]

如果是多维数组,则索引之间用逗号分隔。可以使用…代表省略某几个维度,如果省略则会被认为是该维度全部输出,例如x[...,3] 等效于 x[:,:,:,:,3]。

可以通过for循环迭代多为数组,其内容为低一维度的子数组,如果希望遍历每一个子元素,可以使用flat属性。

    a = np.array([[0, 1, 2, 3],
                  [10, 11, 12, 13],
                  [40, 41, 42, 43]])
    # 输出a第一维(行)的前三个,第二维(列)下标的1~3
    print(a[1:3, 0:3])
    # 输出行的所有,下标为2的列
    print(a[2, ...])
    # 遍历数组
    for row in a:
        print(row)
    # 遍历每个子元素
    for item in a.flat:
        print(item)
     
    '''
    后两行的1~3列:
    [[10 11 12]
     [40 41 42]]
    第三行的所有列:
    [40 41 42 43]
    遍历数组:
    [0 1 2 3]
    [10 11 12 13]
    [40 41 42 43]
    遍历每个元素:
    0
    1
    2
    ......
    41
    42
    43
    '''

除了使用具体数字作为索引,还可以使用numpy数组作为索引。例如当索引i为多维数组时,将会按照i的位置从数组a中取出元素

    a = np.arange(12) ** 2
    print(a)
    i = np.array([1, 3, 5])
    print(a[i])
    # 多维数组索引j
    j = np.array([[3, 4], [9, 7]])
    print(a[j])
     
    '''
    [  0   1   4   9  16  25  36  49  64  81 100 121]
    数组a的1、3、5个元素
    [ 1  9 25]
    通过多为索引j取出a的数据填到对应位置
    [[ 9 16]
     [81 49]]
    '''

当索引数组由单个元素组成时,默认对数组a的第一个维度进行选择。若需要对数组在多个维度上进行索引,则传入多个索引组成的数组i,j并用逗号分隔

    a = np.array(([[0, 1, 2, 3],
                   [4, 5, 6, 7],
                   [8, 9, 10, 11]]))
    # 对a的第一个维度进行选择
    i = np.array([0, 1])
    print(a[i])
    # 对数组a在多个维度上进行选择,同时提供i,j代表取出a的[0,2]、[1,3]两个元素
    j = np.array([2, 3])
    print(a[i, j])
    '''
    选择多维数组a的第0、1两行:
    [[0 1 2 3]
     [4 5 6 7]]
    a的[0,2]、[1,3]两个元素:
    [2 7]
    '''

还可以通过True/False数组代表元素是否被选中,例如下面有一个True/False数组mask,新建一个全为0的2×2数组padded,然后使用一个数组序列[1,2,3]去填充padded,可见mask为True的地方被选择并填充,False的地方未被选中,仍为0.

mask = np.array([[True, False],
                 [True, True]])
padded = np.zeros((2, 2))
padded[mask] = np.array([1, 2, 3])  # 用序列填充被mask选中的位置
print(padded)
'''
[[1. 0.]
 [2. 3.]]
'''

3.3 改变维度

数组的reshape()方法可以将原数组重构成目标维度的数组,例如将一个2×6的数组重构为3×4的数组,

数组在重构时不会修改原数组,而是返回修改后的结果数组

值得注意的是数组在重构和打印时都是从最右边的维度开始往左进行,例如下面的3×4的数组b,先按行排列4个,然后再换行,排列这样的3行。如果是多维,则按这样的行列继续输出。如果数组维度为-1,则会自动计算该维度的大小,例如含有12个元素的数组,第二、第三维是3×2,则第一维就是2

ravel()函数可以将数组展成一维数组。

    a=np.array([[1,2,3,4,5,6],
                [7,8,9,10,11,12]])
    b=a.reshape(3,4)
    print(b)
    # 多维数组,自动计算
    print(a.reshape(-1,3,2))
    # 展开数组
    flatted = b.ravel()
    print(flatted, end=' ')
    '''
    [[ 1  2  3  4]
     [ 5  6  7  8]
     [ 9 10 11 12]]
    2×3×2的多维数组:
    [[[ 1  2]
      [ 3  4]
      [ 5  6]]
     [[ 7  8]
      [ 9 10]
      [11 12]]]
    展开数组:
    [ 1  2  3  4  5  6  7  8  9 10 11 12] 
    '''

transpose()函数可以实现数组转置的功能,例如下面数组a为一个4×3×2的三维数组,通过transpose(2,0,1),其中的0、1、2分别代表数组原来的维度第一、二、三维,在括号中的位置代表转置后的维度,因此结果将数组的第三维放到第一维,第一维放到第二维,第二维放到第三维,即转置为3×2×4的数组。

    a = np.array([
        [[1, 2, 3, 4],
         [5, 6, 7, 8],
         [9, 10, 11, 12]],
        [[13, 14, 15, 16],
         [17, 18, 19, 20],
         [21, 22, 23, 24]]
    ])
    b = a.transpose(2, 0, 1)
    print(b)
    '''
    [[[ 1  5  9]
      [13 17 21]]
     [[ 2  6 10]
      [14 18 22]]
     [[ 3  7 11]
      [15 19 23]]
     [[ 4  8 12]
      [16 20 24]]]
    '''

3.4 数组的合并

numpy的concatenate()可以用于数组的合并,其第一个参数为要合并的数组,放在一个tuple()或list[]中。第二个参数axis指定合并的轴,默认axis=0,即从第一维合并所有子元素

a1 = np.array([[1, 3], [5, 7]])
a2 = np.array([[2, 4], [6, 8]])
a3 = np.concatenate((a1, a2))  # 合并数组
print(a3)
print(np.concatenate((a1, a2), axis=1))  # 指定合并的轴
'''
[[1 3]
 [5 7]
 [2 4]
 [6 8]]
[[1 3 2 4]
 [5 7 6 8]]
'''

numpy的hstack()函数可以在水平方向上合并多个数组,vstack()函数可以在垂直方向上合并多个数组

相反地,hsplit()vsplit()可以拆分为指定数量的数组

    a=np.array([1,2,3])
    b=np.array([4,5,6])
    # 垂直方向合并
    c=np.vstack((a,b))
    print(c)
    # 水平方向合并
    print(np.hstack((a,b)))
    # 水平方向拆分
    print(np.hsplit(c,3))
    '''
    垂直堆叠
    [[1 2 3]
     [4 5 6]]
    水平合并
    [1 2 3 4 5 6]
    水平拆分为三个1×2的:
    [array([[1],
           [4]]), 
    array([[2],
           [5]]), 
    array([[3],
           [6]])]
    '''

3.5 数组的复制

当一个数组对象赋值给一个新的变量时,是新开辟一个存储空间还是只是传递一个引用?答案是引用。

例如执行语句b=a,只是将一个引用传给了b,对b执行的操作会直接影响a。查看a、b两个对象的节点id也是一样的

    a = np.array([1, 2, 3])
    b = a
    # 修改b
    b[0] = 0
    print(a)
    # 输出a、b对象的id
    print(id(a), id(b))
     
    '''
    修改b,a也发生了变化
    [0 2 3]
    查看二者的id
    2290013812656 2290013812656
    '''

通过切片返回数组的视图,修改视图的形状不会影响原数组,但是在视图上修改数据原数组也会改变。在执行del a之后,由于c引用了a,a依旧会存在内存中不会被删除

    c = a[:]
    # 修改视图的形状
    c.shape = 3, 1
    print(c, a)
    # 修改视图c的数据
    c[0] = 1
    print(a[0])
     
    '''
    对视图c的形状做修改,a不会受到影响
    [[0]
     [2]
     [3]] [0 2 3]
    修改c的数据,a也会随之改变:
    1
    '''

通过copy()方法可以生成数据的副本,对副本的操作完全不会影响原数组

    d= a.copy()
    d[0]=5
    # 修改数组的副本d,a不受影响,输出a:[1 2 3]
    print(a)

4、保存文件

numpy通过save()将一个数组arr保存为.npy文件,并且可以通过np.load()读取该文件

如果npy文件中存在序列化的pickled对象,则需要设置属性allow_pickle=True,否则会报错

ValueError: Object arrays cannot be loaded when allow_pickle=False

    np.save("output.npy",arr)
     
    arr = np.load("output.npy", allow_pickle=True)

如果需要储存多个数组,可以通过np.savez()保存为.npz文件,其变量名作为数组的key值,同理可以使用load()读取

    np.savez('array_save.npz',arr1,arr2,arr3)
     
    Arr=np.load('arr_save.npz')
    arr1=Arr['arr1']        # 通过key值取到不同数组

.npy与.npz文件无法手动查看,如果需要查看可以保存为txt文本的格式,通过savetxt()保存,并通过loadtxt()读取

    np.savetxt('data.txt',arr)
     
    data=np.loadtxt('data.txt')

在保存文件时可以通过fmt属性设置输出数组的格式,如下设置保存数据为整型,且后跟一个制表符

np.savetxt("./output.txt", data, fmt='%d')

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 教你利用python如何读取txt中的数据

    教你利用python如何读取txt中的数据

    们使用python的时候经常需要读取txt文件中的内容,下面这篇文章主要给大家介绍了关于利用python如何读取txt中数据的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • python数据库编程 Mysql实现通讯录

    python数据库编程 Mysql实现通讯录

    这篇文章主要为大家详细介绍了python数据库编程,Mysql实现通讯录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • Django ORM 多表查询示例代码

    Django ORM 多表查询示例代码

    这篇文章主要介绍了Django ORM 多表查询,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • Jupyter Notebook输出矢量图实例

    Jupyter Notebook输出矢量图实例

    这篇文章主要介绍了Jupyter Notebook输出矢量图实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • Pycharm连接远程服务器过程图解

    Pycharm连接远程服务器过程图解

    这篇文章主要介绍了Pycharm连接远程服务器过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • VS Code有哪些奇技淫巧(必知)

    VS Code有哪些奇技淫巧(必知)

    VS Code这几年作为一款热门的开发工具,逐渐受到更多开发者的欢迎,今天给大家分享VS Code有哪些奇技淫巧,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • python基础教程之序列详解

    python基础教程之序列详解

    这篇文章主要介绍了python基础教程之序列详解,本文的序列包含元组(tuple)、列表(list)等数据类型,需要的朋友可以参考下
    2014-08-08
  • Python 字典(Dictionary)操作详解

    Python 字典(Dictionary)操作详解

    这篇文章主要介绍了Python 字典(Dictionary)的详细操作方法,需要的朋友可以参考下
    2014-03-03
  • 如何用Python破解wifi密码过程详解

    如何用Python破解wifi密码过程详解

    这篇文章主要介绍了如何用Python破解wifi密码过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Python绘制的二项分布概率图示例

    Python绘制的二项分布概率图示例

    这篇文章主要介绍了Python绘制的二项分布概率图,涉及Python基于numpy、math的数值运算及matplotlib图形绘制相关操作技巧,需要的朋友可以参考下
    2018-08-08

最新评论