NumPy是高性能科学计算和数据分析的基础包,它是pandas等其他各种工具的基础
NumPy的主要功能
- ndarray,一个多维数组结构,高效且节省空间
- 无需循环对整组数据进行快速运算的数学函数
- 线性代数、随机数生成和傅里叶变换功能
安装:pip install numpy
引用:import numpy as np
ndarray-多维数组对象
- 创建ndarray:np.array(array_like)
- 数组与列表的区别
- 数组对象内的元素类型必须相同
- 数组大小不可修改
应用实例1:已知若干家跨国公司的市值(美元),将其换算成人民币
In [8]: import numpy as np In [9]: import random In [10]: a = [random.uniform(100.0,200.0) for i in range(20)] In [11]: a Out[11]: [136.2570275865808, 151.38290478605188, 149.40015231576714, 179.46370837535062, 138.01630196014202, 115.81947317917567, 185.2180195622318, 193.57586013677022, 102.9291187837209, 156.8431052737879, 128.66133657874553, 150.07270364386525, 170.74414812240832, 154.35837117898353, 156.53279511038093, 136.51100109358936, 137.0380675334829, 184.56892243007366, 103.5787671958268, 183.70079830110825] In [12]: a = np.array(a) #创建数组对象 In [13]: a Out[13]: array([136.25702759, 151.38290479, 149.40015232, 179.46370838, 138.01630196, 115.81947318, 185.21801956, 193.57586014, 102.92911878, 156.84310527, 128.66133658, 150.07270364, 170.74414812, 154.35837118, 156.53279511, 136.51100109, 137.03806753, 184.56892243, 103.5787672 , 183.7007983 ]) In [14]: x = 6.8 In [15]: a * x Out[15]: array([ 926.54778759, 1029.40375255, 1015.92103575, 1220.35321695, 938.51085333, 787.57241762, 1259.48253302, 1316.31584893, 699.91800773, 1066.53311586, 874.89708874, 1020.49438478, 1161.06020723, 1049.63692402, 1064.42300675, 928.27480744, 931.85885923, 1255.06867252, 704.33561693, 1249.16542845]) In [16]:
应用实例2:已知购物车中每件商品的价格和商品件数,求总金额
In [20]: a = [random.uniform(10,20) for i in range(20)] In [21]: b = [random.randint(10,20) for i in range(20)] In [22]: a = np.array(a) In [23]: b = np.array(b) In [24]: a * b #支持直接相乘,索引对应的相乘 Out[24]: array([294.79985817, 135.17136305, 341.89322703, 154.99996299, 143.94682133, 147.02696382, 277.0250938 , 325.06409196, 212.4595863 , 279.04606011, 218.0552968 , 163.07537005, 181.32814133, 184.55252831, 142.18846323, 199.10239773, 202.08948928, 154.73513997, 296.18862383, 124.46747136]) In [25]: (a * b).sum() #支持sum求和 Out[25]: 4177.215950463794
常规用法
- dtype 数组元素数据类型
In [26]: a = np.array(range(10)) In [27]: a Out[27]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [28]: a.dtype Out[28]: dtype('int32')
- size 数组元素的个数
In [33]: a = np.array(range(10)) In [34]: a.size Out[34]: 10
- shape 数组的维度大小(元组形式)
In [35]: a = np.array([[1,2,3],[4,5,6]]) In [36]: a.size Out[36]: 6 In [37]: a.shape Out[37]: (2, 3) #两行三列 In [38]: a = np.array([[[1,2,3],[4,5,6]],[[1,2,3],[2,3,3]]]) In [39]: a.size Out[39]: 12 In [40]: a.shape Out[40]: (2, 2, 3) #二维,两行三列
- T 数组的转置(对高维数组而言)
In [41]: a = np.array([[1,2,3],[4,5,6]]) In [42]: a Out[42]: array([[1, 2, 3], [4, 5, 6]]) In [43]: a.T Out[43]: array([[1, 4], [2, 5], [3, 6]])
- ndim 数组的维数
In [45]: a Out[45]: array([[1, 2, 3], [4, 5, 6]]) In [46]: a.ndim Out[46]: 2
NumPy创建
- array() 常规创建,将列表转换成数组,可选择显示指定dtype
In [47]: np.array([1,2,3]) Out[47]: array([1, 2, 3]) In [48]: np.array([1] * 10) Out[48]: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
- zeros() 根据指定形状和dtype创建全0数组
In [52]: a Out[52]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) In [53]: a.dtype Out[53]: dtype('float64') In [54]: a = np.zeros(10, dtype='int') In [55]: a.dtype Out[55]: dtype('int32')
- ones() 根据指定形状和dtype创建全1数组
In [56]: a = np.ones(10) In [57]: a Out[57]: array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) In [58]: a.dtype Out[58]: dtype('float64')
- empty() 根据指定形状和dtype创建空数组(随机值)
In [60]: np.empty(100) Out[60]: array([ 2.39284228e-316, 2.39571364e-316, 2.39452749e-316, 2.39454963e-316, 2.39331288e-316, 2.39453065e-316, 2.39444212e-316, 2.39569151e-316, 2.39530574e-316, 2.39454014e-316, 2.39449271e-316, 2.39339588e-316, 1.48758265e-316, 1.49005061e-316, 1.48729016e-316, 2.14488521e-317, 2.14317772e-317, 2.13932006e-317, 2.14788123e-317, 2.14793656e-317, 2.14724487e-317, 1.48497556e-316, 2.14482197e-317, 2.14732787e-317, 2.14112636e-317, 2.14730020e-317, 2.14324096e-317, 2.14339906e-317, 2.14141094e-317, 2.14721720e-317, 2.20929556e-317, 2.14718953e-317, 2.13919358e-317, 2.14727254e-317, 2.14741088e-317, 2.20926394e-317, 2.14479035e-317, 2.14475873e-317, 2.14320934e-317, 2.14314610e-317, 2.14485359e-317, 2.20932718e-317, 2.14716187e-317, 2.14133980e-317, 2.39570258e-316, 2.39340972e-316, 2.39339865e-316, 2.39569704e-316, 2.39571641e-316, 2.39568321e-316, 2.39579941e-316, 2.18778197e-316, 2.18185081e-316, 2.39569981e-316, 2.39579665e-316, 2.39333778e-316, 2.39572748e-316, 2.39569428e-316, 2.33985972e-316, 2.39456227e-316, 2.39454646e-316, 2.36317646e-316, 2.39240261e-316, 2.38305292e-316, 2.18908077e-316, 2.39232989e-316, 2.39239629e-316, 2.39332671e-316, 2.39443896e-316, 1.49981809e-316, 2.39233305e-316, 2.39222870e-316, 2.39240578e-316, 2.39327138e-316, 2.39326861e-316, 2.39197890e-316, 2.39332118e-316, 2.39331565e-316, 1.49982125e-316, 2.39332395e-316, 2.39239945e-316, 2.39331841e-316, 2.39232673e-316, 2.39443579e-316, -2.12367890e+127, 2.42906426e-313, 7.81051817e-271, -2.90091486e+127, 3.50637145e+151, 7.96738272e-220, 1.10262801e+161, 8.93439283e-311, 1.85505085e-229, 3.70188797e-313, 2.88067937e+214, 2.47148131e-258, 4.02977518e-270, 2.05229784e-289, 1.93878725e-260, 2.90979962e-319])
- arange() range的NumPy版,支持浮点数
In [63]: np.arange(1,10,2) Out[63]: array([1, 3, 5, 7, 9]) In [64]: np.arange(1,10,0.3) Out[64]: array([1. , 1.3, 1.6, 1.9, 2.2, 2.5, 2.8, 3.1, 3.4, 3.7, 4. , 4.3, 4.6, 4.9, 5.2, 5.5, 5.8, 6.1, 6.4, 6.7, 7. , 7.3, 7.6, 7.9, 8.2, 8.5, 8.8, 9.1, 9.4, 9.7])
- linspace() 类似arange,第三个参数为数组长度,或者说分成多少份,和arange另外不同的是linspace不仅能取到起点数,还能取到终点数
In [65]: np.linspace(0,5,3) Out[65]: array([0. , 2.5, 5. ]) In [66]: np.linspace(0,10,50) Out[66]: array([ 0. , 0.20408163, 0.40816327, 0.6122449 , 0.81632653, 1.02040816, 1.2244898 , 1.42857143, 1.63265306, 1.83673469, 2.04081633, 2.24489796, 2.44897959, 2.65306122, 2.85714286, 3.06122449, 3.26530612, 3.46938776, 3.67346939, 3.87755102, 4.08163265, 4.28571429, 4.48979592, 4.69387755, 4.89795918, 5.10204082, 5.30612245, 5.51020408, 5.71428571, 5.91836735, 6.12244898, 6.32653061, 6.53061224, 6.73469388, 6.93877551, 7.14285714, 7.34693878, 7.55102041, 7.75510204, 7.95918367, 8.16326531, 8.36734694, 8.57142857, 8.7755102 , 8.97959184, 9.18367347, 9.3877551 , 9.59183673, 9.79591837, 10. ])
- eye() 根据指定边长和dtype创建单位矩阵 一般在线性代数中用到
In [67]: np.eye(5) #5行5列,渐进是1 Out[67]: array([[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.], [0., 0., 1., 0., 0.], [0., 0., 0., 1., 0.], [0., 0., 0., 0., 1.]])
ndarray-批量运算
数组和标量之间运算
- + - * / // ** > < ==
In [68]: a = np.arange(1,10,3) In [69]: a Out[69]: array([1, 4, 7]) In [70]: a + 1 Out[70]: array([2, 5, 8]) In [71]: a - 1 Out[71]: array([0, 3, 6]) In [72]: a * 3 Out[72]: array([ 3, 12, 21]) In [73]: a / 3 Out[73]: array([0.33333333, 1.33333333, 2.33333333]) In [74]: 1 // a Out[74]: array([1, 0, 0], dtype=int32) In [75]: a ** 0.5 Out[75]: array([1. , 2. , 2.64575131]) In [76]: a > 5 Out[76]: array([False, False, True])
同样大小数组之间运算
In [79]: a = np.linspace(1,7,3) In [80]: b = np.linspace(2,8,3) In [81]: a Out[81]: array([1., 4., 7.]) In [82]: b Out[82]: array([2., 5., 8.]) In [83]: a * b Out[83]: array([ 2., 20., 56.]) In [84]: a > b Out[84]: array([False, False, False]) In [85]: a == b Out[85]: array([False, False, False])
ndarray-索引和切片
一维数组的索引 列表取法:a[0]
In [86]: a = np.arange(1,10,2) In [87]: a[0] Out[87]: 1
多维数组的索引 第一个为行索引,第二个为列索引
- 列表式取法 a[2][3]
- 新式取法 a[2,3]
In [88]: a = np.arange(15).reshape(3,5) #把0-14 15个数构造成3行5列的数组 In [89]: a Out[89]: array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]]) In [90]: a[1][0] Out[90]: 5 In [91]: a[1,0] Out[91]: 5
一维数组切片 取:a[0:4] a[4:] 赋值:a[0:2] = 1
In [92]: a = np.arange(1,10,2) In [93]: a Out[93]: array([1, 3, 5, 7, 9]) In [94]: a[0:4] Out[94]: array([1, 3, 5, 7]) In [95]: a[4:] Out[95]: array([9]) In [96]: a[0:2] = 1 In [97]: a Out[97]: array([1, 1, 5, 7, 9])
这里需要注意的是 切片取值并赋值给变量,改变这个变量的值,会连同改变数组里的值,如果不希望改变原数组的值,需要使用copy,这一点和python里的列表还是有点不同的
copy()方法可以创建数组的深拷贝
In [98]: a Out[98]: array([1, 1, 5, 7, 9]) In [99]: b = a[4:] #切片赋值不会重新开辟空间,只会增加一个索引 In [100]: b Out[100]: array([9]) In [101]: b[0] = 123 #所以在这里会修改a数组的值 In [102]: a Out[102]: array([ 1, 1, 5, 7, 123]) In [106]: c = a[4:].copy() #如果希望切片赋值另开辟空间,需要用copy In [107]: c Out[107]: array([123]) In [108]: c[0] = 321 #此时的修改就不会修改a数组的值 In [109]: a Out[109]: array([ 1, 1, 5, 7, 123])
多维数组的切片 a[1:2, 3:4] a[:,3:5] a[:,1]
In [110]: a = np.arange(15).reshape(3,5) In [111]: a Out[111]: array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]]) In [112]: a[1:,2:4] #1: 行索引切片 2:4 列索引切片 Out[112]: array([[ 7, 8], [12, 13]]) In [113]: a[:,1] Out[113]: array([ 1, 6, 11])
布尔型索引
问题1:给一个数组,选出数组中所有大于5的数
In [117]: a Out[117]: [2, 4, 5, 6, 5, 6, 10, 5, 5, 9] In [118]: list(filter(lambda x:x>5, a)) Out[118]: [6, 6, 10, 9] In [119]: a = np.array(a) In [120]: a[a>5] #答案 Out[120]: array([ 6, 6, 10, 9]) In [121]: a>5 #第一步:这里会对a里面元素进行>5判断,返回一个布尔数组 Out[121]: array([False, False, False, True, False, True, True, False, False, True]) In [122]: a[[False, False, False, True, False, True, True, False, False, True]] #第二步:布尔型索引:将同样大小的布尔数组传入索引,会返回一个由所有True对应元素的数组 Out[122]: array([ 6, 6, 10, 9])
问题2:给一个数组,选出数组中所有大于5的偶数
给一个数组,选出数组中所有大于5的数和偶数
#与,或(优先级比较高,所以记得要给条件加括号) In [125]: a Out[125]: array([ 2, 4, 5, 6, 5, 6, 10, 5, 5, 9]) In [126]: a[(a>5) & (a%2 == 0)] #大于5 同时偶数 Out[126]: array([ 6, 6, 10]) In [127]: a[(a>5) | (a%2 == 0)] #大于5 或偶数 Out[127]: array([ 2, 4, 6, 6, 10, 9])
花式索引
问题1:对于一个数组,选出其第1,3,4,6,7个元素,组成新的数组
In [128]: a Out[128]: array([ 2, 4, 5, 6, 5, 6, 10, 5, 5, 9]) In [129]: a[[2,4,7,8]] Out[129]: array([5, 5, 5, 5])
问题2:对一个二维数组,选出其第一列和第三列,组成新的二维数组
这里留下个小疑问,为什么a[[1,3],[1,3]]这样取是一一对应,而换成列切片就成对应列所有的切片值?
In [132]: a = np.arange(20).reshape(4,5) In [133]: a Out[133]: array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19]]) In [134]: a[0,a[0]>2] #取出第一行,然后对第一行进行大2比较 Out[134]: array([3, 4]) In [135]: a[[1,3],[1,3]] #取出1行1列 3行3列对应的数据 Out[135]: array([ 6, 18]) In [136]: a[1:3,:][:,1:3] #先取出索引行1,2,再在1,2行上去索引列1,2 Out[136]: array([[ 6, 7], [11, 12]]) In [137]: a[[1,3],:][:,[1,3]] #先取出索引行1,3,再在1,3行上取索引列1,3 Out[137]: array([[ 6, 8], [16, 18]])
NumPy-通用函数
通用函数:能同时对数组中所有元素进行运算的函数
一元函数
- abs 绝对值
In [146]: a = np.arange(-5,5) In [147]: a Out[147]: array([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]) In [148]: abs(a) Out[148]: array([5, 4, 3, 2, 1, 0, 1, 2, 3, 4]) In [149]: np.abs(a) Out[149]: array([5, 4, 3, 2, 1, 0, 1, 2, 3, 4]) #取绝对值,和python内置函数的结果无差别
- sqrt 开方
In [150]: a Out[150]: array([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]) In [151]: np.sqrt(a) #开方,负数开方返回一个异常值 C:UserssevenDesktopclient-report estdemo estenvScriptsipython:1: RuntimeWarning: invalid value encountered in sqrt Out[151]: array([ nan, nan, nan, nan, nan, 0. , 1. , 1.41421356, 1.73205081, 2. ])
- 取整家族 floor ceil round trunc
In [7]: import math In [8]: math.floor(1.6) #向小取整 或者说 向下取整 Out[8]: 1 In [9]: math.floor(-1.6) Out[9]: -2 In [10]: math.ceil(1.6) #向大取整 或者说 向上取整 Out[10]: 2 In [11]: math.ceil(-1.6) Out[11]: -1 In [12]: round(1.6) #四舍五入 背0取整 Out[12]: 2 In [13]: round(-1.6) Out[13]: -2 In [14]: int(1.6) #舍弃小数 向0取整 Out[14]: 1 In [15]: int(-1.6) Out[15]: -1 In [16]: a = np.arange(-4.5,5.5) In [17]: a Out[17]: array([-4.5, -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5]) In [18]: np.floor(a) Out[18]: array([-5., -4., -3., -2., -1., 0., 1., 2., 3., 4.]) In [19]: np.ceil(a) Out[19]: array([-4., -3., -2., -1., -0., 1., 2., 3., 4., 5.]) In [20]: np.round(a) Out[20]: array([-4., -4., -2., -2., -0., 0., 2., 2., 4., 4.]) In [21]: np.trunc(a) #对应int Out[21]: array([-4., -3., -2., -1., -0., 0., 1., 2., 3., 4.])
- modf 把一个数的整数和小数部分分开
In [153]: a = np.arange(-4.5,5.5) In [154]: a Out[154]: array([-4.5, -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5]) In [155]: np.modf(a) #获取到 小数组 和 整数组 Out[155]: (array([-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5]), array([-4., -3., -2., -1., -0., 0., 1., 2., 3., 4.])) In [156]: x, y = np.modf(a) In [157]: x Out[157]: array([-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5]) In [158]: y Out[158]: array([-4., -3., -2., -1., -0., 0., 1., 2., 3., 4.])
- 特殊浮点值类型:nan和inf
- nan表示不存在的浮点值(数据分析中,常表示数据缺失值), 并且nan != nan, 所以不能通过相等来判断是否为此类型
- inf表示无限大的浮点值, inf == inf,比任何浮点数都大
- 创建: np.nan np.inf
- 判断类型可以用isnan,isinf
In [159]: 5 / np.arange(0,5) C:UserssevenDesktopclient-report estdemo estenvScriptsipython:1: RuntimeWarning: divide by zero encountered in true_divide Out[159]: array([ inf, 5. , 2.5 , 1.66666667, 1.25 ]) In [160]: np.sqrt(np.arange(-5,5)) C:UserssevenDesktopclient-report estdemo estenvScriptsipython:1: RuntimeWarning: invalid value encountered in sqrt Out[160]: array([ nan, nan, nan, nan, nan, 0. , 1. , 1.41421356, 1.73205081, 2. ]) In [161]: float('nan') #在python里也是有这两种类型的 Out[161]: nan In [162]: float('inf') Out[162]: inf In [163]: a = np.sqrt(np.arange(-5,5)) client-report estdemo estenvScriptsipython:1: RuntimeWarning: invalid value encountered in sqrt In [164]: np.isnan(a) #不能通过相等判断,只能用isnan判断了 Out[164]: array([ True, True, True, True, True, False, False, False, False, False]) In [165]: a[np.isnan(a)] Out[165]: array([nan, nan, nan, nan, nan]) In [166]: a[~(np.isnan(a))] #~取反 Out[166]: array([0. , 1. , 1.41421356, 1.73205081, 2. ]) In [167]: float('inf') > 100000000000000000000000000000 #inf大于任何一个值 Out[167]: True In [168]: b = 5 / np.arange(0,5) client-report estdemo estenvScriptsipython:1: RuntimeWarning: divide by zero encountered in true_divide In [169]: b Out[169]: array([ inf, 5. , 2.5 , 1.66666667, 1.25 ]) In [170]: np.isinf(b) Out[170]: array([ True, False, False, False, False]) In [171]: b[np.isinf(b)] Out[171]: array([inf]) In [172]: b[~(np.isinf(b))] Out[172]: array([5. , 2.5 , 1.66666667, 1.25 ]) In [173]: b[~np.isinf(b)] Out[173]: array([5. , 2.5 , 1.66666667, 1.25 ]) In [174]: b[b!=np.inf] #由于可以用相等来判断是否为同类型,所以可以通过不等来达到取反 Out[174]: array([5. , 2.5 , 1.66666667, 1.25 ]) In [175]: np.inf == np.inf Out[175]: True In [176]: np.nan == np.nan Out[176]: False
其他一元函数exp,log,cos,sin,tan
二元函数
- maximum 和 minimum 两个数组对应索引位置进行比较
In [177]: a = np.array([random.randint(1,10) for i in range(5)]) In [178]: a Out[178]: array([8, 2, 9, 9, 7]) In [179]: b = np.array([random.randint(1,10) for i in range(5)]) In [180]: b Out[180]: array([2, 8, 7, 8, 6]) In [181]: np.maximum(a,b) Out[181]: array([8, 8, 9, 9, 7]) In [182]: np.minimum(a,b) Out[182]: array([2, 2, 7, 8, 6])
其他二元函数 add,substract,multiply,divide,power,mod
NumPy-数学和统计方法
- sum 求和
- mean 求平均数
- std 求标准差
- var 求方差
- min 求最小值
- max 求最大值
- argmin 求最小值索引
- argmax 求最大值索引
In [62]: a Out[62]: array([10, 8, 6, 5, 3]) In [63]: a.sum() #求和 Out[63]: 32 In [64]: a.mean() #平均值 Out[64]: 6.4 In [65]: a.var() #方差 Out[65]: 5.84 In [66]: a.std() #标准差 Out[66]: 2.4166091947189146 In [67]: a.max() #最大值 Out[67]: 10 In [69]: a.min() #最小值 Out[69]: 3 In [70]: a.argmax() #最大值索引 Out[70]: 0 In [71]: a.argmin() #最小值索引 Out[71]: 4
NumPy-随机数生成
- rand 给定形状产生随机数组(0到1之间的数)
- randint 给定形状产生随机整数
- choice 给定形状产生随机选择
- shuffle 与random.shuffle相同
In [72]: random.random() #0-1 随机小数 Out[72]: 0.253928652483257 In [73]: random.randint(1,9) Out[73]: 9 In [74]: random.randint(1,9) Out[74]: 5 In [75]: random.choice(range(1,9)) Out[75]: 4 In [76]: li = [5,6,7,1,3,85,1] In [77]: random.shuffle(li) #打乱列表 In [78]: li Out[78]: [1, 6, 1, 3, 7, 85, 5] In [79]: np.random.randint(0,10) Out[79]: 8 In [80]: np.random.randint(0,10,5) Out[80]: array([2, 3, 2, 1, 8]) In [81]: np.random.randint(0,10,(2,2)) Out[81]: array([[1, 0], [3, 2]]) In [82]: np.random.randint(0,10,(2,2,3)) #numpy中支持多维度数组构造 Out[82]: array([[[4, 4, 4], [7, 5, 3]], [[6, 8, 4], [3, 4, 4]]]) In [83]: np.random.rand(10) Out[83]: array([0.51186616, 0.24771734, 0.13641393, 0.71080895, 0.27003082, 0.57749886, 0.47018439, 0.75806409, 0.79094952, 0.16099402]) In [85]: np.random.choice([1,2,3,4,5],5) Out[85]: array([1, 5, 5, 4, 3]) In [86]: random.uniform(2.0,4.0) #指定范围随机小数 Out[86]: 3.9032782320014907 In [87]: np.random.uniform(2.0,4.0,5) Out[87]: array([3.09650184, 2.05159769, 2.80963563, 3.98015927, 2.77113653])