当前位置:   article > 正文

python之numpy数值分析_numpy 数值解

numpy 数值解

NumPy是使用python进行科学计算的基础包,常用于数据分析。NumPy的主要对象是一个多维数组,该数组可以存储各种类型的数据,但在一个数组内只能存放同一个类型的数据。

基础

数组属性

NumPy的数组对象称为ndarray,其具有以下属性:

属性说明属性说明
ndarray.ndim数组的轴数ndarray.shape数组的形状或大小
ndarray.size数组的元素总数ndarray.dtype描述数组中的元素类型
ndarray.itemsize数组中每个元素的大小(以字节为单位)ndarray.data表示数组中每个元素的大小

如下所示:

import numpy as np

a = np.arange(20).reshape(4, 5)
print("创建一个4行5列的数组:")
print(a)
print("数组的轴数(维度):", a.ndim)
print("数组的形状:", a.shape)
print("数组类型:", a.dtype.name)
print("数组元素的大小:", a.itemsize)
print("数组大小:", a.size)
print("数组a类型:", type(a))
b = np.array([6, 7, 8])
print("数组b类型:", type(b))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
'
运行

创建数组

  1. 使用empty创建数组:创建一个空数组,数组中的元素是随机产生的,如下所示:
import numpy as np

dt = np.empty([2, 2], dtype=int)
print(dt)
  • 1
  • 2
  • 3
  • 4
'
运行
  1. 使用array创建数组,使用python列表创建数组,可以使用dtype自行设置数据类型;在不设置dtype的情况下,从列表中自动推断数据类型。
import numpy as np
dt = np.array([1, 2, 3, 4, 5], dtype="f8")
print("数组:", dt)
print("数组数据类型:", dt.dtype)
dt = np.array([[1], [2]], dtype=complex)
print("数组:", dt)
print("数组数据类型:", dt.dtype)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
'
运行
  1. 使用zeros/ones创建数组:创建一个全0/1的数组,如下所示:
import numpy as np

dt = np.zeros([3, 5], dtype=int)
print("全为0数组:")
print(dt)
dt = np.ones([5, 3], dtype=float)
print("全为1数组:")
print(dt)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
'
运行
  1. 使用arange创建数组:基于一个数据范围来创建数组,如下所示:
import numpy as np

dt = np.arange(10, 30, 5) # 生成一个数据范围在10和30之间、每隔5个数取一个值构成数组。
print(dt)
  • 1
  • 2
  • 3
  • 4
'
运行
  1. 使用linspace创建数组:基于一个数范围来构造数组,与arange中不同的是,其参数Num是指在起始值和结束值之间需要创建多少个数值,而不是步长,如下所示:
import numpy as np

dt = np.linspace(20, 30, num=5)
print("第一个数组:")
print(dt)

print("第二个数组:")
dt = np.linspace(20, 30, num=5, endpoint=False)# endpoint=False,表示不取终点值
print(dt)

print("第三个数组:")
dt = np.linspace(20, 30, num=5, retstep=True)# retstep=True,表示显示出取值的步长
print(dt)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
'
运行
  1. 使用numpy.random.rand创建随机数组,NumPy利用random模块来产生随机数,如下所示:
import numpy as np

dt = np.random.rand(10) # 创建包含10个元素的随机数组
print("第一次生成的数组:")
print(dt)
dt = np.random.rand(10)
print("第二次生成的数组:")
print(dt)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
'
运行
  1. 使用numpy.random.randn创建随机数组,并且其能产生符合正太分布的随机数,如下所示:
import numpy as np

dt = np.random.randn(3, 5)
print("符合正态分布的数组:")
print(dt)
  • 1
  • 2
  • 3
  • 4
  • 5
'
运行
  1. 使用numpy.random.randint创建随机数组,并且所有元素均为整数,如下所示:
import numpy as np

dt = np.random.randint(10, 30, 5) # 在10和30之间产生随机数,并从取5个整数来构成数组。
print("按范围产生随机数组:")
print(dt)
  • 1
  • 2
  • 3
  • 4
  • 5
'
运行
  1. 使用fromfunction可以通过一个函数规则来创建数组,该方法中的shape参数指定了创建数组的规则,如下所示:
 import numpy as np

dt = np.fromfunction(lambda i, j: i + j, (4, 5), dtype=int)# 使用匿名函数,将数组大小为(4,5)的数组的各行号和各列号之和作为数组元素。
print("按函数规则创建数组:")
print(dt)
  • 1
  • 2
  • 3
  • 4
  • 5
'
运行

基本操作

对多维数组的加减乘除的操作会应用到每一个元素上,并创建一个新数组,如下所示,两个形状相同的数组,同一个位置上的元素进行运算,然后产生一个新的数组。

import numpy as np

a = np.array([10, 20, 30, 40, 50])
b = np.arange(5) # 生成的数组为[0,1,2,3,4]
c = a + b
print("数组相加:")
print(c)
print("数组相乘:")# 数组同一位置上的元素相乘。
c = b * a
print(c)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行
当对不同类型的数组进行运算的时候,最终结果的类型会转换为更精确的类型。例如整型和浮点型进行运算,结果是浮点型,这种行为称为向上转换。
  • 1

索引、切片和迭代

  1. 可以向list中那样使用下标进行索引、切片和迭代,如下所示:
import numpy as np

a = np.arange(10)
print(a)
print("通过下标选择元素:", a[5])
print("通过切片选择元素:", a[3:8])
print("通过切片设置步长选择元素:", a[::2])
print("循环数组:")
for item in a:
    print("当前元素是:", item * 5)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行
  1. 在选择数据的时候,由于提供的索引少于轴的数量,因此缺失的索引被认为是完整切片。NumPy支持使用“···”三个点号来表示剩余的轴,例如:一个多维数组N有5个轴,那么:
    N[1,···]等同于N[1,:,:,:,:];
    N[···,3]等同于N[:,:,:,:,3];
    N[1,···,3,:]等同于N[1,:,:,3,:];如下所示,对数据的选取是按维度的顺序进行的。
import numpy as np

a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]).reshape(2, 3, 2)
print("原始数组:")
print(a)
print("三维数组的形状:", a.shape)
print("取第一维的第1行和余下的数据:", a[1, ...])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
'
运行
  1. 使用flat可以将n维数组转换到一维数组中,以遍历列表的方式遍历数组中的所有元素,如下所示:
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]).reshape(2, 3, 2)
for row in a:
    print("当前行数据:")
    print(row)

for el in a.flat:
    print("当前元素:", el)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
'
运行

形状操作

更改形状

数组的形状是每个轴上元素的个数确定的,numpy提供了多种方法来修改数组形状,如下所示:

import numpy as np

a = np.floor(10 * np.random.random((4, 5)))# np.floor():表示返回不大于输入参数的最大整数(向下取整)
print("原始数组形状:", a.shape)

b = a.ravel()
print("将多维数组转为一维数组", b, "新数组的形状:", b.shape)

print("将数组修改为指定形状:")
c = a.reshape(2, 10)
print("新数组形状为:", c.shape)

d = a.T
print("对数组进行行列转换(矩阵转置):", d.shape)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
'
运行

使用以上方法更改形状会创建新的数组,可以调用resize方法避免创建新的数组,如下所示:

import numpy as np

a = np.floor(10 * np.random.random((4, 5)))
print("修改前形状为:", a.shape)
a.resize(2, 10)
print("修改后形状为:", a.shape)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
'
运行

数组堆叠

堆叠就是将多个数组沿不同的轴叠在一起,如下所示:
import numpy as np

a = np.floor(10 * np.random.random((2, 10)))
print("数组a:")
print(a)
b = np.floor(10 * np.random.random((2, 10)))
print("数组b:")
print(b)
print("沿垂直方向堆叠:")
c = np.vstack((a, b))
print(c)
print("沿水平方向堆叠")
d = np.hstack((a, b))
print(d)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

矩阵拆分

import numpy as np

a = np.floor(10 * np.random.random((2, 20)))
print(a)
print("水平方向拆分:")
data = np.hsplit(a, 2)
for item in data:
    print(item)
print("垂直方向拆分:")
data2 = np.vsplit(a, 2)
for item in data2:
    print(item)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
'
运行

除上之外,也可以调用array_split方法将矩阵分成指定大小的数组。

副本、浅拷贝和深拷贝

  1. python中,可变对象是作为引用传递的,因此简单的赋值操作不会创建数据的副本,如下所示:
import numpy as np

a = np.arange(16)
b = a
if b is a:
    print("b和a是一样的")

print("a的地址:", id(a))
print("b的地址:", id(b))
b.shape = 4, 4
print("a的形状为:", a.shape)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
'
运行
  1. 浅拷贝是指两个数据对象不同,但数据是共享的。调用view方法并对数组进行切片,可以创建一个对象的浅拷贝副本,此时需要副本的值,原对象的值也会改变,如下所示:
import numpy as np

a = np.arange(16)
b = a.view()
if b is a:
    print("b和a是同一个对象")
else:
    print("b和a不是同一个对象")

print("判断b的base是否和a一样:", b.base is a)
print("判断b是否存在独立的一份数据拷贝:", b.flags.owndata)
print("修改b的形状:", (4, 4))
b.shape = 4, 4
print("输出a的形状", a.shape)
print("修改b的数据:b[0,2] = 10")
b[0, 2] = 100
print("查看a的数据:", a)
print("数组切片:")
c = a[1:3]
c[1] = 200
print("修改切片后的数组,然后查看对a的影响:", a)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
'
运行
  1. 深拷贝是根据原来的数组创建一个完全独立的副本,互不影响,在数组上使用copy完成深拷贝,如下所示:
import numpy as np

a = np.arange(16)
b = a.copy()
if b is a:
    print("b和a是同一个对象")
else:
    print("b和a不是同一个对象")

b[5] = 200
print("数组b:", b)
print("数组a:", a)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
'
运行

高级索引

通过数组进行索引

  1. 对一维数组进行索引,每一维按照索引数组给定的位置取值,然后构造新的数组,如下所示:
import numpy as np

a = np.arange(10) * 2
print("原始数组:", a)
b = np.array([1, 1, 3, 4])
print("通过b索引的数据:", a[b])
c = np.array([[2, 3], [5, 6]])
print("通过c索引的数据:", a[c])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
'
运行
  1. 对多维数组进行索引,给出的索引数组将从原始数组的第一个维度上进行取值,如下所示:
import numpy as np

data = np.array([[0, 0, 0, 99],
                 [168, 0, 0, 23],
                 [0, 198, 0, 78],
                 [0, 0, 23, 64],
                 [121, 0, 88, 36]])
index = np.array([[1, 2, 3, 4], [0, 2, 1, 3]])# 此处的[1, 2, 3, 4],取到的是data中的第1、2、3、4行数据,[0, 2, 1, 3]取到的是第0、2、1、3行组成的数据
print(data[index])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
'
运行

3.由以上两个示例,可以看出原始数组是一维的,使用二维数组进行索引,最终结果也是二维的;原始数组是二维的,也使用二维数组进行索引,最终结果是三维的,因此使用二维数组索引,最终结果会在原始数组的基础上提升一个维度。

对多维数组的每一个维度提供索引,要求每个维度的索引数必须相同,如下所示:

 import numpy as np

a = (np.arange(16) * 2).reshape(4, 4)
print("原始数组:")
print(a)
b = np.array([[0, 1], [2, 3]])
c = np.array([[1, 2], [3, 3]])
print("两个维度都使用二维数组索引:")
print(a[b, c])
print("第一个维度都使用二维数组索引:")
print(a[b, 1])
print("第二个维度都使用二维数组索引:")
print(a[:, b])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
'
运行
  1. 数组索引的一种常见引用场景是检索数组的极值,如下所示,求每一列上最大值的位置,
  import numpy as np

a = (np.sin(np.arange(12) * 10)).reshape(4, 3)
print("原始数组")
print(a)
max_val_posi = a.argmax(axis=0)
print("每个列上最大值的位置:")
print(max_val_posi)

data_max = a[max_val_posi, range(3)]
print("检索最大值,并返回新的数组:")
print(data_max)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
'
运行

通过布尔索引

  1. 使用与原数组形状相同的布尔数组对整个原始数组进行筛选,如下所示:
import numpy as np

a = np.arange(8).reshape(2, 4)
print("原始数组a:")
print(a)

b = a > 4
print("新的布尔数组b:")
print(b)

print("使用布尔数组进行筛选:")
print(a[b])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
'
运行
  1. 也可以在不同维度上单独设置布尔索引进行筛选,如下所示:
import numpy as np

a = np.arange(8).reshape(2, 4)
print(a)
b1 = np.array([False, True])
b2 = np.array([True, False, True, False])
print("选取第一维的第2行,和所有列")
print(a[b1, :])
print("选取第一维的第2行,第二维的第1,3列")
print(a[b1, b2])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行

通过ix()函数索引

使用ix()函数来构造索引,如下所示:

 import numpy as np

a = np.arange(10).reshape(2, 5)
print(a)

b = np.ix_([0, 1], [2, 3])
print("使用整数数组筛选数据:")
print(a[b])
c = np.ix_([True, True], [1, 3])
print("使用布尔数组筛选数据:")
print(a[c])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
'
运行

排序统计

排序

  1. sort:在数组对象上调用sort会对数组本身进行排序,调用np模块上的sort,则会返回该数组对象的副本,意味着创建一个新的数组,这个新数组是排了序的,如下所示:
import numpy as np

a = np.random.randint(1, 10, size=10)
print("将数组本身排序:")
a.sort()
print(a)

a = np.array([[1, 4, 3], [3, 1, 7], [8, 5, 10], [4, 2, 15]])
print("沿最后一个轴排序:")
print(np.sort(a))

b = np.sort(a, axis=None)
print("将数组所有数据后排序:")
print(b)

c = np.array([[1, 4, 5], [13, 1, 6], [18, 5, 9], [14, 2, 10]])
print("沿第一个轴排序:")
d = np.sort(c, axis=0)
print(d)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
'
运行

对结构化数组,在sort方法中设置参数order即可,如下所示:

import numpy as np

data = [("Wilson", 98, 70), ("Bruce", 60, 98), ("Ivy", 98, 92)]
dtype = [("name", "S10"), ("math_score", int), ("en_score", int)]
a = np.array(data, dtype=dtype) 
b = np.sort(a, order=["math_score", "en_score"])
print("排序后的结果:")
print(b)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
'
运行
  1. lexsort:并不具备排序功能,调用该方法返回数据内各个元素的排序位置,如下所示,(argsort方法同样返回数组中各元素的位置)
import numpy as np

a = [7, 6, 5, 4, 3, 10, 12, 15]
b = [9, 4, 0, 4, 0, 2, 1, 7]
ind = np.lexsort((b, a))
print("lexsort返回a各个元素在数组中的排序位置:")
print(ind)
d = [(a[i], b[i]) for i in ind]
print("通过列表推导式创建的新数组:")
print(d)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行

统计

numpy可以很方便的求解最大值、最小值、均值、方差等统计数据,如下所示:

import numpy as np

a = np.array([7, 6, 5, 4, 3, 10, 12, 15])
print("一维数组各元素求和:", np.sum(a))
print("一维数组求均值:", np.mean(a))
print("一维数组求最大值:", np.max(a))
print("一维数组求方差:", np.std(a))
print("一维数组求最大元素索引:", np.argmax(a))

a = np.array([7, 6, 5, 4, 3, 10, 12, 15]).reshape(4, 2)
print("二维数组各元素迭代求和:", np.cumsum(a))
print("二维数组将全部元素求和:", np.sum(a))
print("二维数组沿轴求和:", np.sum(a, axis=1))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
'
运行

补充:
广播机制:对两个形状相同的数组进行加减乘除等运算,按各对应位置的元素执行运算操作即可。对不同形状的数组进行运算,则需要利用“广播机制”。如下所示,二维数组和一维数组相加,只要两个数组形状得最后一个维度得值相同,或者其中一个数组最后一个维度的值是1,那么即使不同形状也能进行运算。

import numpy as np

a = np.array([7, 6, 5, 4, 3, 10, 12, 15]).reshape(2, 4)
print("二维数组a:")
print(a)
b = np.array([1, 2, 3, 4])
c = a + b
print("二维数组加一维数组:")
print(c)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
'
运行
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/995554
推荐阅读
相关标签
  

闽ICP备14008679号