Python是一门不错的动态语言,其应用的领域非常广泛,如web开发、Linux运维、数据挖掘、机器学习、爬虫、推荐系统等。在学完《廖雪峰Python2.7教程》感觉受益匪浅,掌握了基本的语法之后开始接触用Python进行数据分析。这里向大家推荐两本书《Python数据分析》和《利用Python进行数据分析》,而这两本书也是目前我正在学习的材料,虽然这两本书都是基于Python2.x,但对于Python3.x也能正常运行。 本期将会涉及到Python模块中的numpy,这是一个处理数组的强大模块,而该模块也是其他数据分析模块(如pandas和scipy)的核心。下面将从这5个方面来介绍numpu模块的内容: 1)数组的创建 2)有关数组的属性和函数 3)数组元素的获取--普通索引、切片、布尔索引和花式索引 4)统计函数与线性代数运算 5)随机数的生成 数组的创建 numpy中使用array()函数创建数组,array的首个参数一定是一个序列,可以是元组也可以是列表。 一维数组的创建 可以使用numpy中的arange()函数创建一维有序数组,它是内置函数range的扩展版。 In [1]: import numpy as np In [2]: ls1 = range(10) In [3]: list(ls1) Out[3]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] In [4]: type(ls1) Out[4]: range In [5]: ls2 = np.arange(10) In [6]: list(ls2) Out[6]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] In [7]: type(ls2) Out[7]: numpy.ndarray 通过arange生成的序列就不是简简单单的列表类型了,而是一个一维数组。 如果一维数组不是一个规律的有序元素,而是人为的输入,就需要array()函数创建了。 In [8]: arr1 = np.array((1,20,13,28,22)) In [9]: arr1 Out[9]: array([ 1, 20, 13, 28, 22]) In [10]: type(arr1) Out[10]: numpy.ndarray 上面是由元组序列构成的一维数组。 In [11]: arr2 = np.array([1,1,2,3,5,8,13,21]) In [12]: arr2 Out[12]: array([ 1, 1, 2, 3, 5, 8, 13, 21]) In [13]: type(arr2) Out[13]: numpy.ndarray 上面是由列表序列构成的一维数组。 二维数组的创建 二维数组的创建,其实在就是列表套列表或元组套元组。 In [14]: arr3 = np.array(((1,1,2,3),(5,8,13,21),(34,55,89,144))) In [15]: arr3 Out[15]: array([[ 1, 1, 2, 3], [ 5, 8, 13, 21], [ 34, 55, 89, 144]]) 上面使用元组套元组的方式。 In [16]: arr4 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]]) In [17]: arr4 Out[17]: array([[ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12]]) 上面使用列表套列表的方式。 对于高维数组在将来的数据分析中用的比较少,这里关于高维数组的创建就不赘述了,构建方法仍然是套的方式。 上面所介绍的都是人为设定的一维、二维或高维数组,numpy中也提供了几种特殊的数组,它们是: In [18]: np.ones(3) #返回一维元素全为1的数组 Out[18]: array([ 1., 1., 1.]) In [19]: np.ones([3,4]) #返回元素全为1的3×4二维数组 Out[19]: array([[ 1., 1., 1., 1.], [ 1., 1., 1., 1.], [ 1., 1., 1., 1.]]) In [20]: np.zeros(3) #返回一维元素全为0的数组 Out[20]: array([ 0., 0., 0.]) In [21]: np.zeros([3,4]) #返回元素全为0的3×4二维数组 Out[21]: array([[ 0., 0., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]) In [22]: np.empty(3) #返回一维空数组 Out[22]: array([ 0., 0., 0.]) In [23]: np.empty([3,4]) #返回3×4二维空数组 Out[23]: array([[ 0., 0., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]) 有关数组的属性和函数 当一个数组构建好后,我们看看关于数组本身的操作又有哪些属性和函数: In [24]: arr3 Out[24]: array([[ 1, 1, 2, 3], [ 5, 8, 13, 21], [ 34, 55, 89, 144]]) In [25]: arr3.shape #shape方法返回数组的行数和列数 Out[25]: (3, 4) In [26]: arr3.dtype #dtype方法返回数组的数据类型 Out[26]: dtype('int32') In [27]: a = arr3.ravel() #通过ravel的方法将数组拉直(多维数组降为一维数组) In [28]: a Out[28]: array([ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]) In [29]: b = arr3.flatten() #通过flatten的方法将数组拉直 In [30]: b Out[30]: array([ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]) 两者的区别在于ravel方法生成的是原数组的视图,无需占有内存空间,但视图的改变会影响到原数组的变化。而flatten方法返回的是真实值,其值的改变并不会影响原数组的更改。 通过下面的例子也许就能明白了: In [31]: b[:3] = 0 In [32]: arr3 Out[32]: array([[ 1, 1, 2, 3], [ 5, 8, 13, 21], [ 34, 55, 89, 144]]) 通过更改b的值,原数组没有变化。 In [33]: a[:3] = 0 In [34]: arr3 Out[34]: array([[ 0, 0, 0, 3], [ 5, 8, 13, 21], [ 34, 55, 89, 144]]) a的值变化后,会导致原数组跟着变化。 In [35]: arr4 Out[35]: array([[ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12]]) In [36]: arr4.ndim #返回数组的维数 Out[36]: 2 In [37]: arr4.size #返回数组元素的个数 Out[37]: 12 In [38]: arr4.T #返回数组的转置结果 Out[38]: array([[ 1, 5, 9], [ 2, 6, 10], [ 3, 7, 11], [ 4, 8, 12]]) 如果数组的数据类型为复数的话,real方法可以返回复数的实部,imag方法返回复数的虚部。 介绍完数组的一些方法后,接下来我们看看数组自身有哪些函数可操作: In [39]: len(arr4) #返回数组有多少行 Out[39]: 3 In [40]: arr3 Out[40]: array([[ 0, 0, 0, 3], [ 5, 8, 13, 21], [ 34, 55, 89, 144]]) In [41]: arr4 Out[41]: array([[ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12]]) In [42]: np.hstack((arr3,arr4)) Out[42]: array([[ 0, 0, 0, 3, 1, 2, 3, 4], [ 5, 8, 13, 21, 5, 6, 7, 8], [ 34, 55, 89, 144, 9, 10, 11, 12]]) 横向拼接arr3和arr4两个数组,但必须满足两个数组的行数相同。 In [43]: np.vstack((arr3,arr4)) Out[43]: array([[ 0, 0, 0, 3], [ 5, 8, 13, 21], [ 34, 55, 89, 144], [ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12]]) 纵向拼接arr3和arr4两个数组,但必须满足两个数组的列数相同。 In [44]: np.column_stack((arr3,arr4)) #与hstack函数具有一样的效果 Out[44]: array([[ 0, 0, 0, 3, 1, 2, 3, 4], [ 5, 8, 13, 21, 5, 6, 7, 8], [ 34, 55, 89, 144, 9, 10, 11, 12]]) In [45]: np.row_stack((arr3,arr4)) #与vstack函数具有一样的效果 Out[45]: array([[ 0, 0, 0, 3], [ 5, 8, 13, 21], [ 34, 55, 89, 144], [ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12]]) reshape()函数和resize()函数可以重新设置数组的行数和列数: In [46]: arr5 = np.array(np.arange(24)) In [47]: arr5 #此为一维数组 Out[47]: 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]) In [48]: a = arr5.reshape(4,6) In [49]: a Out[49]: 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]]) 通过reshape函数将一维数组设置为二维数组,且为4行6列的数组。 In [50]: a.resize(6,4) In [51]: a Out[51]: 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]]) 通过resize函数会直接改变原数组的形状。 数组转换:tolist将数组转换为列表,astype()强制转换数组的数据类型,下面是两个函数的例子: In [53]: b = a.tolist() In [54]: b Out[54]: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]] In [55]: type(b) Out[55]: list In [56]: c = a.astype(float) In [57]: c Out[57]: 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.]]) In [58]: a.dtype Out[58]: dtype('int32') In [59]: c.dtype Out[59]: dtype('float64') 数组元素的获取 通过索引和切片的方式获取数组元素,一维数组元素的获取与列表、元组的获取方式一样: In [60]: arr7 = np.array(np.arange(10)) In [61]: arr7 Out[61]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [62]: arr7[3] #获取第4个元素 Out[62]: 3 In [63]: arr7[:3] #获取前3个元素 Out[63]: array([0, 1, 2]) In [64]: arr7[3:] #获取第4个元素即之后的所有元素 Out[64]: array([3, 4, 5, 6, 7, 8, 9]) In [65]: arr7[-2:] #获取末尾的2个元素 Out[65]: array([8, 9]) In [66]: arr7[::2] #从第1个元素开始,获取步长为2的所有元素 Out[66]: array([0, 2, 4, 6, 8]) 二维数组元素的获取: In [67]: arr8 = np.array(np.arange(12)).reshape(3,4) In [68]: arr8 Out[68]: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) In [69]: arr8[1] #返回数组的第2行 Out[69]: array([4, 5, 6, 7]) In [70]: arr8[:2] #返回数组的前2行 Out[70]: array([[0, 1, 2, 3], [4, 5, 6, 7]]) In [71]: arr8[[0,2]] #返回指定的第1行和第3行 Out[71]: array([[ 0, 1, 2, 3], [ 8, 9, 10, 11]]) In [72]: arr8[:,0] #返回数组的第1列 Out[72]: array([0, 4, 8]) In [73]: arr8[:,-2:] #返回数组的后2列 Out[73]: array([[ 2, 3], [ 6, 7], [10, 11]]) In [74]: arr8[:,[0,2]] #返回数组的第1列和第3列 Out[74]: array([[ 0, 2], [ 4, 6], [ 8, 10]]) In [75]: arr8[1,2] #返回数组中第2行第3列对应的元素 Out[75]: 6 布尔索引,即索引值为True和False,需要注意的是布尔索引必须输数组对象。 In [76]: log = np.array([True,False,False,True,True,False]) In [77]: arr9 = np.array(np.arange(24)).reshape(6,4) In [78]: arr9 Out[78]: 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]]) In [79]: arr9[log] #返回所有为True的对应行 Out[79]: array([[ 0, 1, 2, 3], [12, 13, 14, 15], [16, 17, 18, 19]]) In [80]: arr9[-log] #通过负号筛选出所有为False的对应行 Out[80]: array([[ 4, 5, 6, 7], [ 8, 9, 10, 11], [20, 21, 22, 23]]) 举一个场景,一维数组表示区域,二维数组表示观测值,如何选取目标区域的观测? In [81]: area = np.array(['A','B','A','C','A','B','D']) In [82]: area Out[82]: array(['A', 'B', 'A', 'C', 'A', 'B', 'D'], dtype=' In [83]: observes = np.array(np.arange(21)).reshape(7,3) In [84]: observes Out[84]: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11], [12, 13, 14], [15, 16, 17], [18, 19, 20]]) In [85]: observes[area == 'A'] Out[85]: array([[ 0, 1, 2], [ 6, 7, 8], [12, 13, 14]]) 返回所有A区域的观测。 In [86]: observes[(area == 'A') | (area == 'D')] #条件值需要在&(and),|(or)两端用圆括号括起来 Out[86]: array([[ 0, 1, 2], [ 6, 7, 8], [12, 13, 14], [18, 19, 20]]) 返回所有A区域和D区域的观测。 当然,布尔索引也可以与普通索引或切片混合使用: In [87]: observes[area == 'A'][:,[0,2]] Out[87]: array([[ 0, 2], [ 6, 8], [12, 14]]) 返回A区域的所有行,且只获取第1列与第3列数据。 花式索引:实际上就是将数组作为索引将原数组的元素提取出来 In [88]: arr10 = np.arange(1,29).reshape(7,4) In [89]: arr10 Out[89]: 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], [25, 26, 27, 28]]) In [90]: arr10[[4,1,3,5]] #按照指定顺序返回指定行 Out[90]: array([[17, 18, 19, 20], [ 5, 6, 7, 8], [13, 14, 15, 16], [21, 22, 23, 24]]) In [91]: arr10[[4,1,5]][:,[0,2,3]] #返回指定的行与列 Out[91]: array([[17, 19, 20], [ 5, 7, 8], [21, 23, 24]]) In [92]: arr10[[4,1,5],[0,2,3]] Out[92]: array([17, 7, 24]) 请注意!这与上面的返回结果是截然不同的,上面返回的是二维数组,而这条命令返回的是一维数组。 如果想使用比较简单的方式返回指定行以列的二维数组的话,可以使用ix_()函数 In [93]: arr10[np.ix_([4,1,5],[0,2,3])] Out[93]: array([[17, 19, 20], [ 5, 7, 8], [21, 23, 24]]) 这与arr10[[4,1,5]][:,[0,2,3]]返回的结果是一致的。 -------------------------------------------------------------------------------------------------------- 由于正文部分不能超过20000字符,接下来的部分将在《Python数据分析之numpy学习(二)》中继续讲解。 -------------------------------------------------------------------------------------------------------- 使用Python进行数据分析,一般都会使用到numpy,pandas,scipy和matplotlib等模块,而numpy是最为基础的模块,其他模块的使用都是以numpy为核心,所以这里讲解了有关numpy的方方面面,这部分的学习非常重要,希望感兴趣的朋友多看看这方面的文档和动手操作。 每天进步一点点2015 学习与分享,取长补短,关注小号! |
|