- 1.本系列基于新生大学课程《Python编程&数据科学入门》和公开的参考资料;
- 2.文章例子基于python3.6,使用Windows系统(除了安装,其余基本没有影响);
- 3.我是纯小白,所以,错误在所难免,体系会逐渐成熟,我会经常进行更新;如果您发现了错误,也烦请帮我指出来,在此先谢过了。
Numpy是Python的一个基础包,它的全名是Numercial Python,是Python高性能科学计算和数据分析的关键所在,也是Python如此成功的一个重要原因。
使用Numpy可以实现下面这些功能:
- 任意维度的数组
- 异常高效快速的运算
- 线性代数和随机数的生成
- 可集成C、C++以及Fortran等语言,提供API接口
总之,Numpy功能强大,是大数据和人工智能的必修课。
文章主要内容如下:
- 数组对象的定义
- 创建数组的方法
- 数组的属性
- 数组的索引和切片
- 数组的基本数据类型
- 数组的运算
- 数组的输出
- 数组的统计方法
- 一个数组的逻辑运算函数
数组对象的定义
Numpy的核心对象是数组(Ndarray),ndarray 是一个通用的同构多维数据容器。
有两点需要注意:
- 第一,所有元素都必须是相同类型;
- 第二,数组可以是无限维度。
import Numpy as np #引入Numpy库,并简写为np
一维数组有点像列表,二维数组像表格。但数组中的元素这能是同一种数据类型,这是其高效运行的关键因素。更简洁,更高效。
创建数组的方法
1)通过array函数
数组接受一切序列对象,然后通过函数产生一个新的含有数据的Numpy数组。
** 示例1
import numpy as np #在使用Numpy前,必须导入这个库。
list1 = [3, 4, 5.5, 9]
array1 = np.array(list1)
array1
输出如下:
array([ 3. , 4. , 5.5, 9. ])
** 示例2
import numpy as np #在使用Numpy前,必须导入这个库。
list2 = [[1,3,5,7],[2,4,6,8]]
array2 = np.array(list2)
array2
输出如下:
array([[1, 3, 5, 7],
[2, 4, 6, 8]])
2)用zeros和ones函数快速创建数组
- 分别创建制定长度或形状的全0和全1的数组
np.zeros(12)
输出如下:
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
- 用数组创建多维函数:
np.ones((2,4))
输出如下:
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
3)用empty函数创建
- 可以创建一个没有具体值的数组。
注意,不是空值,而是一些未初始化的垃圾值。
np.empty((3,2))
输出如下:
array([[ 2.49914608e-47, 1.39371627e+06],
[ 4.84026180e+15, 1.49082394e-76],
[ 0.00000000e+00, 0.00000000e+00]])
4)arange函数
- 可以创建一定范围的数组,类似于range函数。它的语法仍然是arange(sart, end, step)
np.arange(12)
输出如下:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
np.arange(2, 10, 2)
输出如下:
array([2, 4, 6, 8])
- 结合reshape可以创建多维数组
np.arange(10).reshape(2,5)
输出如下:
array([0,1,2,3,4],
[5,6,7,8,9])
5)用ones_like、zeros_like和empty_like
可以根据一个数组创建一个全1、全0和只分配空间的数组。
np.zeros_like(array2) # 以前已经赋过值的函数
输出如下:
array([[0, 0, 0, 0],
[0, 0, 0, 0]])
6)eye函数
可以创建一个正方的N*N的矩阵(二维数组);
- 用random函数。可以生成一些随机的数据源。
np.random.randn(3,5)
输出如下:
array([[ 0.67201938, 1.26250439, -0.75518549, -0.96637329, 0.20020499],
[ 1.46767699, 0.03292811, 1.24308473, 0.19780962, -2.23047114],
[ 1.2278105 , 0.88424898, -2.11662492, 0.30141536, -1.32447466]])
数组的属性
每个数组ndarray都有shape和dtype,也就是形状和类型。
- ndarray.ndim :数组的维数。
每一个线性的数组称之为轴(axis),秩(rank)就是描述轴的数量。维数等于秩。
array2.ndim
输出如下:
2
- ndarray.shape :数组的形状。
array2.shape
输出如下:
(2,4)
它可以改变数组的形状。
import numpy as np
arr01 = np.arange(1,16)
arr01.shape = (3,5)
arr01
输出
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
它返回一个元组,这个元组就是表示各个维度的大小。
- ndarray.size:数组元素的个数。
等于shape属性中元组元素的乘积。
array2.size
输出如下:
8
- ndarray.dtype:数组元素的类型。
array2.dtype
输出如下:
dtype('int32')
- ndarray.itemsize:数组中每个元素的字节大小。
array2.itemsize
输出如下:
4
Numpy的索引和切片
索引是选取数据的一个元素,维度降低;而切片是选取数据的子集,维度保持不变,只是空间变小了。
- 一维数组,使用[]进行,与列表是一样的。
比如:arr[3],arr[2:3]
- 二维数组,使用两个参数,逗号隔开,先索引列,再索引行,用[]表示。
arr3 = np.empty((4,5))
arr3[3,2]
arr3[2:3,2]
索引得到的是第4列(列3),而切片得到的是第3至第4列,所以输出如下:
array([ 5.56218858e+180])
1.9497344566623563e+160
注意:得到的这两个值的意义是不同的。第一个是一个索引,是一个元素值,而第二个是一个二维数组,只是只有一行一列而已。如果想要得到一个元素的值,要采用arr3[2:3,2][0]的方法。
三维及以上维度的数组的也是类似的。
- 布尔型索引
Numpy允许用另一个数组的布尔值作为数组的索引。
比如:
item1 = np.array(['book', 'write', 'run', 'program', 'run', 'book'])
再使用随机数生成一个数组:
data = np.random.randn(6,4)
先对item1数组进行布尔运算,得到一个布尔型的数组
item1 == 'book'
array([ True, False, False, False, False, True], dtype=bool)
这个布尔型的数组就可以用于数组索引。
data[item1 == 'book']
输出的值是对应这个布尔型进行索引的。所以,第一行和最后一行被输出:
array([[-0.90089307, 0.36295259, -1.67628201, -0.39765334],
[-0.49065895, 0.9847132 , -1.07655711, -1.25794759]])
注意:布尔型数组的长度必须和被索引的轴的长度保持一致。
- 数组的索引和切片是原始数组的视图
原始数组的视图,也就是说原来的数组不是被复制了,而是被引用了,任何改变都会影响到原来的数组。
score = np.array([59, 65, 70, 88, 49, 98])
score[4] = 60
score1 = score[0:2]
score1[0] = 60
score
输出如下:
array([60, 65, 70, 88, 60, 98])
两个值都被修改为60了。
如果不想改变arr2里面的值,可以用.copy方法
score2 = score[0:2].copy()
score2[0] = 59
score2
输出如下:
array([59, 65])
score
输出的是
array([60, 65, 70, 88, 60, 98])
也就是说切片score2里面的60被修改为59,但是原来的数组score并没有被修改。
数组的基本数据类型
与Python的数据类型稍微有点差异。
- 用dtype查询数组的数据类型
- 用astype可以将数组类型进行转换。
- 将dtype和astype结合,将一个数组的类型装换为与另一个数组的类型相同
例1
arr = np.array([2,34,5,9])
arr.dtype
输出如下:
dtype('int32'
例2
arr_f = arr.astype(np.float64)
arr_f.dtype
输出如下:
dtype('float64')
注意:用astype函数会立马创建出一个数组,即使和之前的相同。而不会改变之前的数组的类型。
# coding: utf-8
import numpy as np
arr = np.arange(10)
arr.dtype # 得到类型的结果‘int32’
arr.astype(np.float) # 转换为float格式
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
arr.dtype # 查询arr的类型
结果仍然是int32
dtype('int32')
例子3
arr_f = arr.astype(np.float64)
arr_f.dtype
输出如下:
dtype('float64')
数组的运算
- 数组与单个数之间的运算
对数组进行任何算数运算,都会对数组内所有的元素进行运算。这通常被叫做矢量化(vectorization)。
比如:
arr3 = np.zeros((4, 3, 3))
arr4 = arr3 + 1
arr4
输出如下:
array([[[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]],
[[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]],
[[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]],
[[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]]])
所有的元素都+1。
- 相同的数组还可以直接运算
比如:
arr5 = np.arange(10)
arr6 = np.ones(10)
这是两个一维的数组。两者相加:
arr5+arr6
输出如下:
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
每一个元素都对应相加了。
- 不同维度的数组也可以运算
运算的时候,低维度的数组先要将自己广播为一个高维度的数组,再按照同维度数组进行处理。
print(np.ones((2,10)) +arr5)
arr5只有一个维度,而np.ones((2,10))有两个维度。所以,在运算的时候,arr5先按照np.ones((2,10))的第二维度的长度将维度复制,np.ones((2,10))的第二维有2行,所以,arr5复制1份,在相加时,它实际使用的是:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
所以,输出如下:
[[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]]
数组的输出
一维数组被打印成行,二维数组组成矩阵,三维以上数组组成矩阵列表。
a = np.arange(6)
print(a)
输出如下:
[0 1 2 3 4 5]
b = np.arange(12).reshape(4,3)
print(b)
输出如下:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
c = np.arange(24),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]]]
如果一个数组的长度太长,Numpy会自动把中间的省略,只打印两端的内容。
d = np.arange(10000).reshape(100, 100)
print(d)
输出如下:
[[ 0 1 2 ..., 97 98 99]
[ 100 101 102 ..., 197 198 199]
[ 200 201 202 ..., 297 298 299]
...,
[9700 9701 9702 ..., 9797 9798 9799]
[9800 9801 9802 ..., 9897 9898 9899]
[9900 9901 9902 ..., 9997 9998 9999]]
可以通过printoptions参数来让Numpy强制打印整个数组。
set_printoptions(threshold = 'nan')
数组的统计方法
np.sum(ndarray, axis = n),求和。
arr01 = np.arange(15).reshape(3,5)
np.sum(arr01)
arr01
np.sum(arr01, 1)
arr01
输出如下:
7.0
array([ 5., 6., 7., 8., 9.])
不指定某行或某列的,对所有元素求值。
另外,还有其他的一些统计方法:
- mean,计算平均值。
- max,计算最大值。
- min,计算最小值
数组的逻辑运算函数
numpy.where函数非常神奇,它是x if condition else y的矢量化版本。
arr = np.random.randn(10) #生成一个一维数组。
arr
任务:把小于0的负数改成- 1,把大于0的改成1。
如果采用if函数,可以用这样的方法:
for i in range(10):
if arr[i]>0:
arr[i]=1
else:
arr[i]= -1
arr
用np.where则简单的多。
np.where(arr >0, 1 , -1)
生成随机数
用numpy.random可以快速生成随机数,它比Python内置的random函数快了不止一个数量级。
samples = np.random.normal(size=(4,4)) # normal函数是一个生成标准正态分布的随机函数。
random还有很多其他的函数:
知识本身不是力量,“知识+持续的行动”才是!
我是陶肚,每天陪你读点书。如果喜欢,请帮忙点赞或分享出去。