一. python简介
1. python 具有丰富强大的库,常被称为胶水语言,能够把用其他语言制作的各种模块很轻松地联结在一起
2. python强制使用空白符(white space)作为语句缩进。
3. 可以使用 py2exe等包转换成系统能够执行的文件。
4. Python的瓶颈不在于自身语言的运行时间,在于一些网络速度等外在因素的影响。
二. Python库
1. python版本
常用的有2.7和3.5两个版本,这两个版本不完全兼容。但就目前Windows的环境而言,Python2.7对于数据分析领域就足够用了,但3.5更多用于web开发。当然,也可以使用 2to3.py 实现两个版本之间的转换。
D:>python 2to3.py t1.py RefactoringTool: Skipping optional fixer: buffer RefactoringTool: Skipping optional fixer: idioms RefactoringTool: Skipping optional fixer: set_literal RefactoringTool: Skipping optional fixer: ws_comma RefactoringTool: Refactored t1.py --- t1.py (original) +++ t1.py (refactored) @@ -1 +1 @@ -print 'all tasks has been finished!' +print('all tasks has been finished!') RefactoringTool: Files that need to be modified: RefactoringTool: t1.py
不推荐大家使用上面这个转换的库,因为官网上说这个库会随着时间发生剧烈的变化。
2. pip
pip是安装python包的推荐工具:https://pypi.python.org/pypi/pip
也可以手动更换pip中的数据源:pip install -l https://pypi.tuna.tsinghua.edu.cn/simple numpy
pip会在数据源中查找符合你系统配置的最新版的安装包进行自动安装。
3. numpy
为Python提供快速的多维数组处理能力
4. pandas
在numpy基础上提供了更多了数据读写工具
5. scipy
在numpy基础上添加了众多科学计算工具包
6.matplotlib
Python丰富的绘图库,主要针对二维绘图,有少数的三维绘图函数
三. 数据生成
1. list, array
标准Python的列表list中,元素本质是对象
如:L=[1,2,3],需要3个指针和三个整数对象,对于数值运算比较浪费内存和CPU。
因此,numpy提供了ndarray(N-dimensional array object)对象:存储单一数据类型的多维数组。
# # 1.使用array创建 # 通过array函数传递list对象 L = [1, 2, 3, 4, 5, 6] print "L = ", L a = np.array(L)
print "a = ", a
print type(a), type(L)
# # 若传递的是多层嵌套的list,将创建多维数组
b = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print b
2. 改变数组的大小和形状
# # # # # 数组大小可以通过其shape属性获得 print a.shape print b.shape # # # # 也可以强制修改shape b.shape = 4, 3 print b # # 注:从(3,4)改为(4,3)并不是对数组进行转置,而只是改变每个轴的大小,数组元素在内存中的位置并没有改变 # # # # 当某个轴为-1时,将根据数组元素的个数自动计算此轴的长度 b.shape = 2, -1 print b print b.shape # b.shape = 3, 4 print b # # # # 使用reshape方法,可以创建改变了尺寸的新数组,原数组的shape保持不变 c = b.reshape((4, -1)) print "b = ", b print 'c = ', c
3. 数组的存储,类型
# # # # 数组b和c共享内存,修改任意一个将影响另外一个 b[0][1] = 20 print "b = ", b print "c = ", c # # # # # 数组的元素类型可以通过dtype属性获得 print a.dtype print b.dtype # # # # # # # # # # 可以通过dtype参数在创建时指定元素类型 d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.float) f = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.complex) print d print f # # # # 如果更改元素类型,可以使用astype安全的转换 f = d.astype(np.int) print f # # # # # # # 但不要强制仅修改元素类型,如下面这句,将会以int来解释单精度float类型 d.dtype = np.int print d下面是上面代码中倒数第二个d, 和f的输出
[[ 1. 2. 3. 4.] [ 5. 6. 7. 8.] [ 9. 10. 11. 12.]] [[ 1.+0.j 2.+0.j 3.+0.j 4.+0.j] [ 5.+0.j 6.+0.j 7.+0.j 8.+0.j] [ 9.+0.j 10.+0.j 11.+0.j 12.+0.j]]
4. 使用函数创建
# 如果生成一定规则的数据,可以使用NumPy提供的专门函数 # arange函数类似于python的range函数:指定起始值、终止值和步长来创建数组 # 和Python的range类似,arange同样不包括终值;但arange可以生成浮点类型,而range只能是整数类型 np.set_printoptions(linewidth=100, suppress=True) a = np.arange(1, 10, 0.5) print a # # # # linspace函数通过指定起始值、终止值和元素个数来创建数组,缺省包括终止值 b = np.linspace(1, 10, 10) print 'b = ', b # # 可以通过endpoint关键字指定是否包括终值 c = np.linspace(1, 10, 10, endpoint=False) print 'c = ', c # # # 和linspace类似,logspace可以创建等比数列 # # 下面函数创建起始值为10^1,终止值为10^2,有10个数的等比数列 d = np.logspace(1, 4, 4, endpoint=True, base=2) print d # # # # # # # # # # 下面创建起始值为2^0,终止值为2^10(包括),有10个数的等比数列 f = np.logspace(0, 10, 11, endpoint=True, base=2) print f # # # # # 使用 frombuffer, fromstring, fromfile等函数可以从字节序列创建数组 s = 'abcdzzzz' g = np.fromstring(s, dtype=np.int8) print g # #
下面为输出结果:
[ 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5 7. 7.5 8. 8.5 9. 9.5] b = [ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.] c = [ 1. 1.9 2.8 3.7 4.6 5.5 6.4 7.3 8.2 9.1] [ 2. 4. 8. 16.] [ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512. 1024.] [ 97 98 99 100 122 122 122 122]
5. 存取
1)常规办法
# 数组元素的存取方法和Python的标准方法相同 a = np.arange(10) print a # # # 获取某个元素 print a[3] # # # # # 切片[3,6),左闭右开 print a[3:6] # # # 省略开始下标,表示从0开始 print a[:5] # # # 下标为负表示从后向前数 print a[3:] # # 步长为2 print a[1:9:2] # # # # # # 步长为-1,即翻转 print a[::-1] # # 切片数据是原数组的一个视图,与原数组共享内容空间,可以直接修改元素值 a[1:4] = 10, 20, 30 print a # # 因此,在实践中,切实注意原始数据是否被破坏,如: b = a[2:5] b[0] = 200 print a
[0 1 2 3 4 5 6 7 8 9] 3 [3 4 5] [0 1 2 3 4] [3 4 5 6 7 8 9] [1 3 5 7] [9 8 7 6 5 4 3 2 1 0] [ 0 10 20 30 4 5 6 7 8 9] [ 0 10 200 30 4 5 6 7 8 9]
2)整数/布尔数组存取
# 3.2.1 # 根据整数数组存取:当使用整数序列对数组元素进行存取时, # 将使用整数序列中的每个元素作为下标,整数序列可以是列表(list)或者数组(ndarray)。 # 使用整数序列作为下标获得的数组不和原始数组共享数据空间。 a = np.logspace(0, 9, 10, base=2) print a i = np.arange(0, 10, 2) print i # # # 利用i取a中的元素 b = a[i] print b # # # b的元素更改,a中元素不受影响 b[2] = 1.6 print b print a # # 3.2.2 # 使用布尔数组i作为下标存取数组a中的元素:返回数组a中所有在数组b中对应下标为True的元素 # 生成10个满足[0,1)中均匀分布的随机数 a = np.random.rand(10) print a # # 大于0.5的元素索引 print a > 0.5 # # # 大于0.5的元素 b = a[a > 0.5] print b # # # 将原数组中大于0.5的元素截取成0.5 a[a > 0.5] = 0.5 print a # # # # # b不受影响 print b
[ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.] [0 2 4 6 8] [ 1. 4. 16. 64. 256.] [ 1. 4. 1.6 64. 256. ] [ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.] [ 0.6863079 0.43770902 0.06801346 0.75436358 0.94302857 0.79214232 0.08905118 0.50204237 0.20263459 0.67341405] [ True False False True True True False True False True] [ 0.6863079 0.75436358 0.94302857 0.79214232 0.50204237 0.67341405] [ 0.5 0.43770902 0.06801346 0.5 0.5 0.5 0.08905118 0.5 0.20263459 0.5 ] [ 0.6863079 0.75436358 0.94302857 0.79214232 0.50204237 0.67341405]
3)切片
# 3.3 二维数组的切片 # [[ 0 1 2 3 4 5] # [10 11 12 13 14 15] # [20 21 22 23 24 25] # [30 31 32 33 34 35] # [40 41 42 43 44 45] # [50 51 52 53 54 55]] a = np.arange(0, 60, 10) # 行向量 print 'a = ', a b = a.reshape((-1, 1)) # 转换成列向量 print b c = np.arange(6) print c f = b + c # 行 + 列 print f # # 合并上述代码: a = np.arange(0, 60, 10).reshape((-1, 1)) + np.arange(6) print a # # # 二维数组的切片 print '++++++++++++++' print a[[0, 1, 2], [2, 3, 4]] print a[4, [2, 3, 4]] print a[4:, [2, 3, 4]] print '+++++++++++++' i = np.array([True, False, True, False, False, True]) print i print a[i] print a[i, 3]
a = [ 0 10 20 30 40 50] [[ 0] [10] [20] [30] [40] [50]] [0 1 2 3 4 5] [[ 0 1 2 3 4 5] [10 11 12 13 14 15] [20 21 22 23 24 25] [30 31 32 33 34 35] [40 41 42 43 44 45] [50 51 52 53 54 55]] [[ 0 1 2 3 4 5] [10 11 12 13 14 15] [20 21 22 23 24 25] [30 31 32 33 34 35] [40 41 42 43 44 45] [50 51 52 53 54 55]] ++++++++++++++ [ 2 13 24] [42 43 44] [[42 43 44] [52 53 54]] +++++++++++++ [ True False True False False True] [[ 0 1 2 3 4 5] [20 21 22 23 24 25] [50 51 52 53 54 55]] [ 3 23 53]
上面代码中,
a[i]中索引 i 因为是布尔数组,所以它实际上是对对应行的选择,TRUE为选择,FALSE为不选择。
6.numpy与Python数学库的时间比较
for j in np.logspace(0, 7, 8): x = np.linspace(0, 10, j) start = time.clock() y = np.sin(x) t1 = time.clock() - start x = x.tolist() start = time.clock() for i, t in enumerate(x): x[i] = math.sin(t) t2 = time.clock() - start print j, ": ", t1, t2, t2/t1
1.0 : 8.00000000001e-06 9.00000000015e-06 1.12500000002 10.0 : 0.000125 0.000319 2.552 100.0 : 1.20000000001e-05 0.000231 19.2499999998 1000.0 : 0.000138 0.000307 2.22463768116 10000.0 : 0.000383 0.002946 7.69190600522 100000.0 : 0.003997 0.029284 7.32649487115 1000000.0 : 0.038909 0.326851 8.40039579532 10000000.0 : 0.390234 2.951487 7.5633773582
从上面的运行结果可以看出来,一般情况下,numpy的效率比Python数学库要快,平均快7倍左右
7. 元素去重
# 4.2 元素去重 # 4.2.1直接使用库函数 a = np.array((1, 2, 3, 4, 5, 5, 7, 3, 2, 2, 8, 8)) print '原始数组:', a # # # 使用库函数unique b = np.unique(a) print '去重后:', b # # 4.2.2 二维数组的去重,结果会是预期的么? c = np.array(((1, 2), (3, 4), (5, 6), (1, 3), (3, 4), (7, 6))) print '二维数组: ', c print '去重后:', np.unique(c) # # # 4.2.3 方案1:转换为虚数 r, i = np.split(c, (1, ), axis=1) x = r + i * 1j x = c[:, 0] + c[:, 1] * 1j print '转换成虚数:', x print '虚数去重后:', np.unique(x) print np.unique(x, return_index=True) # 思考return_index的意义 idx = np.unique(x, return_index=True)[1] print '二维数组去重: ', c[idx] # # 4.2.3 方案2:利用set print '去重方案2: ', np.array(list(set([tuple(t) for t in c])))原始数组: [1 2 3 4 5 5 7 3 2 2 8 8]
去重后: [1 2 3 4 5 7 8] 二维数组: [[1 2] [3 4] [5 6] [1 3] [3 4] [7 6]] 去重后: [1 2 3 4 5 6 7] 转换成虚数: [ 1.+2.j 3.+4.j 5.+6.j 1.+3.j 3.+4.j 7.+6.j] 虚数去重后: [ 1.+2.j 1.+3.j 3.+4.j 5.+6.j 7.+6.j] (array([ 1.+2.j, 1.+3.j, 3.+4.j, 5.+6.j, 7.+6.j]), array([0, 3, 1, 2, 5])) 二维数组去重: [[1 2] [1 3] [3 4] [5 6] [7 6]] 去重方案2: [[1 2] [5 6] [7 6] [1 3] [3 4]]
从上面输出结果可以看出:
a. 直接使用np.unique(c)为二维数组去重,不能达到理想的结果。因为unique会默认将输入的数组拉成一维的,然后去重。
b. 对于二维数组去重,一般会选择先将其转成虚数去重,然后再还原成二维。但该种方式会打乱数组里面元素的顺序,所以我们可以令参数return_index=true来让其放回各个元素原始的索引。
c. 使用set来去重需要先将数组转成list然后再进行操作。
8.三维数组去重
# 4.3 stack and axis a = np.arange(1, 7).reshape((2, 3)) b = np.arange(11, 17).reshape((2, 3)) c = np.arange(21, 27).reshape((2, 3)) d = np.arange(31, 37).reshape((2, 3)) print 'a = ', a print 'b = ', b print 'c = ', c print 'd = ', d s = np.stack((a, b, c, d), axis=0) print 'axis = 0 ', s.shape, ' ', s s = np.stack((a, b, c, d), axis=1) print 'axis = 1 ', s.shape, ' ', s s = np.stack((a, b, c, d), axis=2) print 'axis = 2 ', s.shape, ' ', s a = np.arange(1, 10).reshape(3,3) print a b = a + 10 print b print np.dot(a, b) ###矩阵乘法 print a * b ##矩阵元素相乘 a = np.arange(1, 10) print a b = np.arange(20,25) print b print np.concatenate((a, b)) ###连接
a = [[1 2 3] [4 5 6]] b = [[11 12 13] [14 15 16]] c = [[21 22 23] [24 25 26]] d = [[31 32 33] [34 35 36]] axis = 0 (4, 2, 3) [[[ 1 2 3] [ 4 5 6]] [[11 12 13] [14 15 16]] [[21 22 23] [24 25 26]] [[31 32 33] [34 35 36]]] axis = 1 (2, 4, 3) [[[ 1 2 3] [11 12 13] [21 22 23] [31 32 33]] [[ 4 5 6] [14 15 16] [24 25 26] [34 35 36]]] axis = 2 (2, 3, 4) [[[ 1 11 21 31] [ 2 12 22 32] [ 3 13 23 33]] [[ 4 14 24 34] [ 5 15 25 35] [ 6 16 26 36]]] [[1 2 3] [4 5 6] [7 8 9]] [[11 12 13] [14 15 16] [17 18 19]] [[ 90 96 102] [216 231 246] [342 366 390]] [[ 11 24 39] [ 56 75 96] [119 144 171]] [1 2 3 4 5 6 7 8 9] [20 21 22 23 24] [ 1 2 3 4 5 6 7 8 9 20 21 22 23 24]
函数stack实现多个数组堆叠的功能。从运行结果可以看出,当
axis=0时, 是将a, b, c, d四个数组分别作为元素组成新的列向量中的元素;
axis=1时,是分别将a, b, c, d四个数组中的第一个元素组成一个新的列元素,第二个元素也是同样的,最后组成一个列向量。
axis=2时,是将a,b,c,d四个数组先拉成一维,然后分别取四个数组中相同位置的元素组成新的列向量中的元素。