numpy 类库是数据分析的利器, 用于高性能的科学计算和数据分析. 使用 python 进行数据分析, numpy 这个类库是必须掌握的. numpy 并没有提供强大的数据分析功能, 而是它提供的 ndarray 数据结构能够让你快速的处理海量的数据.
shape 和 dtype 属性
ndarray 是 numpy 的多维数组对象, 是 numpy 类库中主要的数据结构, 它有两个重要的属性, shape 和 dtype,shape 是描述数组维度的元组, dtype 用于说明数组数据类型.
- data = [1,2,3,4,5]
- arr1 = np.array(data)
- arr1
- Out[6]: array([1, 2, 3, 4, 5])
- arr1.shape
- Out[7]: (5,)
- arr1.dtype
- Out[8]: dtype('int32')
上面代码说明可 arr1 是长度为 5 的一维数组, 数据类型是 int32.
ndarray 数组的数据都是整数时, 数据类型是 int32, 当有小数时, 数据类型则是 float64.
ndarray 数组中的数据必须是同一类型, 如果有不同类型的数据, dtype 为 < U11.
numpy 主要用于处理数据, 因此 ndarray 数组中的数据必须是同一数据类型, 否则无法进行数学计算.
创建 ndarray
numpy 提供了 array 函数创建 ndarray 对象, array 函数要传入一个 list 列表类型的对象.
- list1 = [1.2,2.3,4.6,7.8]
- ndarray1 = np.array(list1)
- ndarray1
- Out[22]: array([1.2, 2.3, 4.6, 7.8])
传入的 list 列表是等长的多维列表时, 创建的是多维的 ndarray 数组对象.
- list2 = [[1.2,2.3,4.6,7.8],[12.2,13.5,1.6,9.8]]
- ndarray2 = np.array(list2)
- ndarray2
- Out[25]:
- array([[ 1.2, 2.3, 4.6, 7.8],
- [12.2, 13.5, 1.6, 9.8]])
多维列表的长度不一致时, 生成 ndarray 对象的数据类型 dtype 就变成 object, 不是具体的数据类型.
- list3 = [[1.2,2.3,4.6,7.8],[12.2,13.5,1.6,9.8,0.8]]
- ndarray3 = np.array(list3)
- ndarray3
- Out[28]:
- array([list([1.2, 2.3, 4.6, 7.8]), list([12.2, 13.5, 1.6, 9.8, 0.8])],
- dtype=object)
numpy 还提供了 zeros 和 ones 两个方法分别用于创建值为 0 或者 1 的数组.
使用 zero 方法创建数组值为 0 的 ndarray 数组:
- np.zeros(5)// 创建长度为 5, 数组值都为 0 的 ndarray 一维数组
- np.zeros((3,4))// 创建 3 行 4 列, 数组值都为 0 的二维数组
- np.zeros((3,4,5))// 创建维度为 3, 值为 0 的 ndarray 三维数组.
只用 ones 方法创建数组值都为 1 的 ndarray 数组:
- np.ones(5)// 创建长度为 5, 数组值都为 1 的 ndarray 一维数组
- np.ones((3,4))// 创建 3 行 4 列, 数组值都为 1 的二维数组
- np.ones((3,4,5))// 创建维度为 3, 值为 1 的 ndarray 三维数组.
arange()方法直接调用 python 内置的 range()函数生成初始值为 0 步长为 1 的数组:
- data3 = np.arange(13)
- data3
- Out[12]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
empty()方法创建一个新的数组, 数组值是随机生成, 用于占用内存空间:
- data4 = np.empty((2,2))
- data4
- Out[20]:
- array([[7.32086553e-315, 1.01777082e-311],
- [0.00000000e+000, 7.31249282e-315]])
类型转换
ndarray 提供 astype 方法将数据类型转换为其他的数据类型.
将浮点数转为整数时, 会自动截取掉小数部分:
- data5 = np.array([2.2,3.4,5.6])
- data6 = data5.astype(np.int32)
- data6
- Out[23]: array([2, 3, 5])
astype 可以将全是数字的字符串数组转换为数值形式:
- data7 = np.array(['2.4','3.5','4.6'])
- data8 = data7.astype(np.float64)
- data8
- Out[34]: array([2.4, 3.5, 4.6])
数组间的数学运算
两个数组之间是可以进行加减乘除间的数学运算.
两个数组之间的相加:
- data1 = np.array([1,2,3,4])
- data2 = np.array([5,6,7,8])
- data3 = data1 +data2
- data3
- Out[38]: array([ 6, 8, 10, 12])
两个数组之间相减:
- data1 = np.array([1,2,3,4])
- data2 = np.array([5,6,7,8])
- data3 = data1 - data2
- data3
- Out[45]: array([-4, -4, -4, -4])
两个数组之间相乘:
- data1 = np.array([1,2,3,4])
- data2 = np.array([5,6,7,8])
- data3 = data1 * data2
- data3
- Out[49]: array([ 5, 12, 21, 32])
两个数组之间相除:
- data1 = np.array([1,2,3,4])
- data2 = np.array([5,6,7,8])
- data3 = data1 / data2
- data3
- Out[53]: array([0.2 , 0.33333333, 0.42857143, 0.5 ])
两个数组之间进行数学运算时, 数组之间的 shape 对象值必须一致, 就是长度必须一致. 否则会报 ValueError: operands could not be broadcast together with shapes 的错误:
- data1 = np.array([1,2,3,4])
- data2 = np.array([5,6,7,8,9])
- data3 = data1+ data2
上面的代码会报 ValueError: operands could not be broadcast together with shapes (4,) (5,) 错误, data1 数组的 shape 为(4,),data2 的 shape 为(5,), 两者不一样, 无法进行数学运算.
数组的索引和切片
通过索引可以访问 NumPy 数组某个位置上的数值. 数组索引从 0 开始, 于长度 - 1 结束:
- data1 = np.arange(10)
- data1.size
- Out[73]: 10
- data1[0]
- Out[74]: 0
- data1[9]
- Out[75]: 9
- data1[10]
在上面的代码中, 长度为 10 的一维度数组 data1, 索引从 0 开始, 于 9(长度 10-1)结束. 通过 data1[9]访问到数组中的第 10 个元素, 如果通过 data1[10], 则会出现 IndexError: index 10 is out of bounds for axis 0 with size 10 的错误, 俗称数组越界.
这是一维数组的情况, 对于多维数组, 要想访问某个具体元素时, 必须指定这个元素在每一个维度的索引位置:
- data1 = [[[1,2,3],[4,5,6]],[[7,8,9,],[10,11,12]]]
- data1[1][1][1]
- Out[85]: 11
上述代码中 data1 是一个 2X2X3 的三维数组, 要想访问 11, 必须指定三个维度上的索引 data1[1][1][1].
data1[1][1]返回的结果是 1 维的数组:
- data1[1][1]
- Out[86]: [10, 11, 12]
data1[1]返回的是 2 维的数组:
- data1[1]
- Out[87]: [[7, 8, 9], [10, 11, 12]]
data1[1][1][1]和 data1[1,1,1]的效果一样, 返回的数值都是 11.
NumPy 提供在 ndarray 数组上进行切片的操作, 返回的是 ndarray 数组的子视图.
- data1 = np.arange(10)
- data1[1:4]
- Out[91]: array([1, 2, 3])
- data1[:4]
- Out[92]: array([0, 1, 2, 3])
- data1[4:]
- Out[93]: array([4, 5, 6, 7, 8, 9])
data1[1:4]切片操作返回的是从索引 1 开始, 到索引 4 结束, 不包括索引 4 的元素的数组.
data1[:4]切片操作是从索引 0 开始, 到索引 4 结束, 不包括索引 4 的元素的数组.
data1[4:]切片操作返回的是从索引 4 开始到最后一个元素的数组.
切片操作返回的是原数组的视图, 不是重新生成一个数组, 通过对这个切片做赋值操作, 就可以修改原数组对应索引位置上元素的数值:
- data1 = np.arange(10)
- data1[4:]=10
- data1
- Out[98]: array([ 0, 1, 2, 3, 10, 10, 10, 10, 10, 10])
data1 数组从索引 4 开始到最后一个索引 9 上的元素数值都变为 10.
二维及以上的多维数组, 也可以支持切片操作, 但是比一维数组要复杂些:
- data1 = np.array([[1,2,3],[4,5,6],[7,8,9]])
- data1
- Out[100]:
- array([[1, 2, 3],
- [4, 5, 6],
- [7, 8, 9]])
- data1[:2]
- Out[101]:
- array([[1, 2, 3],
- [4, 5, 6]])
- data1[:2,:2]
- Out[102]:
- array([[1, 2],
- [4, 5]])
- data1[:2,1:]
多维数组的切片, 可在每个维度都进行切片操作.
布尔型数组
顾名思义, 布尔型数组就是指数组的元素时布尔值 True 和 False.
变量的比较运算产生的结果是布尔型的, ndarray 数组的比较运算也不例外, 结果也是布尔类型的, 因此可以将一个数字类型或者字符类型的 ndarray 数字通过比较运算转换为布尔型数组:
- data1 = np.array(['Tom','Yong','Jim','John'])
- data1 == 'Tom'
- Out[111]: array([ True, False, False, False])
上面的代码首先创建一个字符类型的 ndarray 数组 data1, 接着对数组进行比较操作, data1 == 'Tom', 如果数组中的元素等于'Tom', 则返回 True, 否则返回 False.
布尔型数值一个最经常的用法是设置值:
- arr = np.random.randn(3,4)
- arr
- Out[62]:
- array([[ 0.52428143, -1.04842533, -1.00102911, -0.86488208],
- [ 3.20965669, 0.4379931 , -0.82962251, 0.63862152],
- [-1.03235591, -1.17507334, -0.01953273, -1.13759955]])
- arr[arr<0] = 0
- arr
- Out[64]:
- array([[0.52428143, 0. , 0. , 0. ],
- [3.20965669, 0.4379931 , 0. , 0.63862152],
- [0. , 0. , 0. , 0. ]])
上面的代码是将 arr 数组中小于零的元素设置为 0.
数组转置
数组转置和线性代数中矩阵转置一样. NumPy 提供 transpose 方法和特殊属性 T 实现数组转置.
- data1 = np.arange(4)
- data1
- Out[71]: array([0, 1, 2, 3])
- data1.T
- Out[72]: array([0, 1, 2, 3])
一维数组的转置还是数组本身.
- data1 = np.arange(14).reshape(2,7)
- data1
- Out[74]:
- array([[ 0, 1, 2, 3, 4, 5, 6],
- [ 7, 8, 9, 10, 11, 12, 13]])
- data1.T
- Out[75]:
- array([[ 0, 7],
- [ 1, 8],
- [ 2, 9],
- [ 3, 10],
- [ 4, 11],
- [ 5, 12],
- [ 6, 13]])
二维数组的转置是将行和列对应位置的元素互相调换.
特殊属性 T 只适用于一维和二维数组, 对于三维以上的数组, 必须使用 transpose 方法才可以实现数组转置.
调用 transpose 方法时需要传入一个元组, 用于指定按照哪些轴进行转置. 元组的元素个数和数组的维度要保持一致. 如果适合 3 维数组, 那么元组个数也必须是 3.
- data1 = np.arange(24).reshape(2,3,4)
- data1
- Out[107]:
- 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]]])
- data1.transpose((2,1,0))
- Out[108]:
- array([[[ 0, 12],
- [ 4, 16],
- [ 8, 20]],
- [[ 1, 13],
- [ 5, 17],
- [ 9, 21]],
- [[ 2, 14],
- [ 6, 18],
- [10, 22]],
- [[ 3, 15],
- [ 7, 19],
- [11, 23]]])
上面代码先是创建一个 2x3x4 的三维数组, 然后调用 transpose((2,1,0))方法实现数组转置. data1 数组的轴用数字 0,1,2 表示 (类似三维空间中的 x,y,z 轴). 调用 transpose((2,1,0)) 时, 元组 (2,1,0) 表示将 data1 的第 0 轴和第 2 轴置换, 1 轴不变.
数组置换返回的是源数据的视图, 不会重新生成新的数组.
来源: https://www.cnblogs.com/airnew/p/10432944.html