资讯专栏INFORMATION COLUMN

Python 数据科学常用包 (一) Numpy

Dean / 2483人阅读

摘要:是什么今天开始会陆续为大家带来数据科学常用包的基础用法数据分析的工作涉及到大量的数值运算,一个高效方便的科学计算工具是必不可少的。

NumPy是什么?

今天开始会陆续为大家带来数据科学常用包的基础用法

数据分析的工作涉及到大量的数值运算,一个高效方便的科学计算工具是必不可少的。Python语言一开始并不是设计为科学计算使用的语言,随着越来越多的人发现Python的易用性,逐渐出现了关于Python的大量外部扩展,Numpy (Numeric Python)就是其中之一。

Numpy提供了大量的数值编程工具,可以方便地处理向量、矩阵等运算,极大地便利了人们在科学计算方面的工作。另一方面,Python是免费,相比于花费高额的费用使用Matlab,Numpy的出现使Python得到了更多人的青睐。

我们可以简单看一下如何开始使用NumPy:

import numpy as np
numpy.version.full_version
"1.16.4"


二、NumPy对象:数组

NumPy中的基本对象是同类型的多维数组(homogeneous multidimensional array),这和C++中的数组是一致的,例如字符型和数值型就不可共存于同一个数组中。先上例子:

a = np.arange(20)
print(a)
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]

这里我们生成了一个一维数组a,从0开始,步长为1,长度为20。Python中的计数是从0开始的,R和Matlab的使用者需要小心。

我们可以通过"type"函数查看a的类型,这里显示a是一个array:

type(a)
numpy.ndarray


通过函数"reshape",我们可以重新构造一下这个数组,例如,我们可以构造一个4*5的二维数组,其中"reshape"的参数表示各维度的大小,且按各维顺序排列(两维时就是按行排列,这和R中按列是不同的):

a = a.reshape(4, 5)
print(a)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]

构造更高维的也没问题:

a = a.reshape(2, 2, 5)
print(a)
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]]

既然a是array,我们还可以调用array的函数进一步查看a的相关属性:"ndim"查看维度;"shape"查看各维度的大小;"size"查看全部的元素个数,等于各维度大小的乘积;"dtype"可查看元素类型;"dsize"查看元素占位(bytes)大小。

a.ndim
3



a.shape
(2, 2, 5)



a.size
20



a.dtype
dtype("int32")


三、创建数组

数组的创建可通过转换列表实现,高维数组可通过转换嵌套列表实现:

raw = [0,1,2,3,4]
a = np.array(raw)
a
array([0, 1, 2, 3, 4])



raw = [[0,1,2,3,4], [5,6,7,8,9]]
b = np.array(raw)
b
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])


一些特殊的数组有特别定制的命令生成,如4*5的全零矩阵:

d = (4, 5)
np.zeros(d)
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])


默认生成的类型是浮点型,可以通过指定类型改为整型:

d = (4, 5)
np.ones(d, dtype=int)
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1]])


[0, 1)区间的随机数数组:

np.random.rand(5)
array([0.80378557, 0.09833667, 0.95280995, 0.17707594, 0.80651926])


服从正态分布的随机数组:

np.random.randn(5)
array([ 0.678737  , -1.14965615, -1.40492579,  1.22479651,  0.2751816 ])


四、数组操作

简单的四则运算已经重载过了,全部的"+","-","*","/"运算都是基于全部的数组元素的,以加法为例:

a = np.array([[1.0, 2], [2, 4]])
print ("a:
",a)

b = np.array([[3.2, 1.5], [2.5, 4]])
print ("b:
",b)
print ("a+b:
",a+b)
a:
 [[1. 2.]
 [2. 4.]]
b:
 [[3.2 1.5]
 [2.5 4. ]]
a+b:
 [[4.2 3.5]
 [4.5 8. ]]

这里可以发现,a中虽然仅有一个与元素是浮点数,其余均为整数,在处理中Python会自动将整数转换为浮点数(因为数组是同质的),并且,两个二维数组相加要求各维度大小相同。当然,NumPy里这些运算符也可以对标量和数组操作,结果是数组的全部元素对应这个标量进行运算,还是一个数组:

print ("3 * a 
",3*a)
print ("b + 1.8 
",b )
3 * a :
 [[ 3.  6.]
 [ 6. 12.]]
b + 1.8 
 [[3.2 1.5]
 [2.5 4. ]]

类似C++,"+="、"-="、"*="、"/="操作符在NumPy中同样支持:

a /= 2
a
array([[0.5, 1. ],
       [1. , 2. ]])


开根号求指数也很容易:

print(a)
[[0.5 1. ]
 [1.  2. ]]


print ("np.exp:
",np.exp(a))
np.exp:
 [[1.64872127 2.71828183]
 [2.71828183 7.3890561 ]]


print ("np.sqrt:
",np.sqrt(a))
np.sqrt:
 [[0.70710678 1.        ]
 [1.         1.41421356]]


print ("np.square:
",np.square(a))
np.square:
 [[0.25 1.  ]
 [1.   4.  ]]


print ("np.power:
",np.power(a,3))
np.power:
 [[0.125 1.   ]
 [1.    8.   ]]

需要知道二维数组的最大最小值怎么办?想计算全部元素的和、按行求和、按列求和怎么办?NumPy的ndarray类已经做好函数了:

a = np.arange(20).reshape(4,5)
a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])



print("sum of all elements in a: " + str(a.sum()))
print("maximum element in a: " + str(a.max()))
print("minimum element in a: " + str(a.min()))
print("maximum element in each row of a: " + str(a.max(axis=1)))
print("minimum element in each column of a: " + str(a.min(axis=0)))
sum of all elements in a: 190
maximum element in a: 19
minimum element in a: 0
maximum element in each row of a: [ 4  9 14 19]
minimum element in each column of a: [0 1 2 3 4]

科学计算中大量使用到矩阵运算,除了数组,NumPy同时提供了矩阵对象(matrix)。矩阵对象和数组的主要有两点差别:一是矩阵是二维的,而数组的可以是任意正整数维;二是矩阵的"*"操作符进行的是矩阵乘法,乘号左侧的矩阵列和乘号右侧的矩阵行要相等,而在数组中"*"操作符进行的是每一元素的对应相乘,乘号两侧的数组每一维大小需要一致。数组可以通过asmatrix或者mat转换为矩阵,或者直接生成也可以:

a = np.arange(20).reshape(4, 5)
a = np.asmatrix(a)
print(type(a))

b = np.matrix("1.0 2.0; 3.0 4.0")
print(type(b))



再来看一下矩阵的乘法,这使用arange生成另一个矩阵b,arange函数还可以通过arange(起始,终止,步长)的方式调用生成等差数列,注意含头不含尾。

b = np.arange(2, 45, 3).reshape(5, 3)
b = np.mat(b)
print(b)
[[ 2  5  8]
 [11 14 17]
 [20 23 26]
 [29 32 35]
 [38 41 44]]

回到我们的问题,矩阵a和b做矩阵乘法:

print ("matrix a:
",a)
print("matrix b:
",b)

c = a * b
print("matrix c:
",c)
matrix a:
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
matrix b:
 [[ 2  5  8]
 [11 14 17]
 [20 23 26]
 [29 32 35]
 [38 41 44]]
matrix c:
 [[ 290  320  350]
 [ 790  895 1000]
 [1290 1470 1650]
 [1790 2045 2300]]

五、数组元素访问

数组和矩阵元素的访问可通过下标进行,以下均以二维数组(或矩阵)为例:

a = np.array([[3.2, 1.5], [2.5, 4]])
print(a[0][1])
print(a[0, 1])
1.5
1.5

可以通过下标访问来修改数组元素的值:

b = a
a[0][1] = 2.0
print(a)
print(b)
[[3.2 2. ]
 [2.5 4. ]]
[[3.2 2. ]
 [2.5 4. ]]

现在问题来了,明明改的是a0,怎么连b0也跟着变了?这个陷阱在Python编程中很容易碰上,其原因在于Python不是真正将a复制一份给b,而是将b指到了a对应数据的内存地址上。想要真正的复制一份a给b,可以使用copy:

a = np.array([[3.2, 1.5], [2.5, 4]])
b = a.copy()
a[0][1] = 2.0
print ("a:",a)
print ("b:",b)
a: [[3.2 2. ]
 [2.5 4. ]]
b: [[3.2 1.5]
 [2.5 4. ]]

若对a重新赋值,即将a指到其他地址上,b仍在原来的地址上:

a = np.array([[3.2, 1.5], [2.5, 4]])
b = a
a = np.array([[2, 1], [9, 3]])
print ("a:
",a)
print ("b:
",b)
a:
 [[2 1]
 [9 3]]
b:
 [[3.2 1.5]
 [2.5 4. ]]

利用":"可以访问到某一维的全部数据,例如取矩阵中的指定列:

a = np.arange(20).reshape(4, 5)
print ("a:
",a)
print ("the 2nd and 4th column of a::
",a[:,[1,3]])
a:
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
the 2nd and 4th column of a::
 [[ 1  3]
 [ 6  8]
 [11 13]
 [16 18]]

稍微复杂一些,我们尝试取出满足某些条件的元素,这在数据的处理中十分常见,通常用在单行单列上。下面这个例子是将第一列大于5的元素(10和15)对应的第三列元素(12和17)取出来:

a[:, 2][a[:, 0] > 5]
array([12, 17])


可使用where函数查找特定值在数组中的位置:

loc = numpy.where(a==11)
print(loc)
print(a[loc[0][0], loc[1][0]])
(array([2], dtype=int64), array([1], dtype=int64))
11

六、数组操作

还是拿矩阵(或二维数组)作为例子,首先来看矩阵转置:

a = np.random.rand(2,4)
print ("a:
",a)
a = np.transpose(a)
print ("a is an array, by using transpose(a):
",a)

b = np.random.rand(2,4)
b = np.mat(b)
print ("b:
",b)
print ("b is a matrix, by using b.T:
",b.T)
a:
 [[0.49632956 0.65061015 0.36037379 0.29664563]
 [0.18319505 0.45525932 0.08422801 0.75167911]]
a is an array, by using transpose(a):
 [[0.49632956 0.18319505]
 [0.65061015 0.45525932]
 [0.36037379 0.08422801]
 [0.29664563 0.75167911]]
b:
 [[0.51087064 0.2058778  0.88659661 0.78428426]
 [0.62716285 0.46838085 0.63015861 0.69754748]]
b is a matrix, by using b.T:
 [[0.51087064 0.62716285]
 [0.2058778  0.46838085]
 [0.88659661 0.63015861]
 [0.78428426 0.69754748]]

矩阵求逆:

import numpy.linalg as nlg
a = np.random.rand(2,2)
print ("a:
",a)
ia = nlg.inv(a)
print ("inverse of a:
",ia)
print ("a * inv(a):
",a * ia)
a:
 [[0.7748124  0.08125528]
 [0.99696367 0.73251292]]
inverse of a:
 [[ 1.50551971 -0.16700242]
 [-2.04904025  1.59245703]]
a * inv(a):
 [[ 1.16649535 -0.01356983]
 [-2.04281868  1.16649535]]

求特征值和特征向量

a = np.random.rand(3,3)
eig_value, eig_vector = nlg.eig(a)

print ("eigen value:
",eig_value)
print ("eigen vector:
",eig_vector)
eigen value:
 [ 1.75590394+0.j         -0.25188941+0.08867887j -0.25188941-0.08867887j]
eigen vector:
 [[ 0.33976986+0.j          0.47679494-0.21597791j  0.47679494+0.21597791j]
 [ 0.81509742+0.j          0.24255425+0.21077809j  0.24255425-0.21077809j]
 [ 0.46922557+0.j         -0.78915154+0.j         -0.78915154-0.j        ]]

按列拼接两个向量成一个矩阵:

a = np.array((1,2,3))
b = np.array((2,3,4))
print(np.column_stack((a,b)))
[[1 2]
 [2 3]
 [3 4]]

在循环处理某些数据得到结果后,将结果拼接成一个矩阵是十分有用的,可以通过vstack和hstack完成:

a = np.random.rand(2,2)
b = np.random.rand(2,2)
print ("a:
",a)
print ("b:
",b)
c = np.hstack([a,b])
d = np.vstack([a,b])
print("horizontal stacking a and b:
",c)
print("vertical stacking a and b:
",d)
a:
 [[0.50331973 0.49651025]
 [0.89325327 0.31245265]]
b:
 [[0.35846554 0.56841584]
 [0.88041789 0.81287829]]
horizontal stacking a and b:
 [[0.50331973 0.49651025 0.35846554 0.56841584]
 [0.89325327 0.31245265 0.88041789 0.81287829]]
vertical stacking a and b:
 [[0.50331973 0.49651025]
 [0.89325327 0.31245265]
 [0.35846554 0.56841584]
 [0.88041789 0.81287829]]

七、缺失值

缺失值在分析中也是信息的一种,NumPy提供nan作为缺失值的记录,通过isnan判定。

a = np.random.rand(2,2)
a[0, 1] = np.nan
print(np.isnan(a))
[[False  True]
 [False False]]

nan_to_num可用来将nan替换成0,pandas中提供能指定nan替换值的函数。

print(np.nan_to_num(a))
[[0.04279427 0.        ]
 [0.08386045 0.3567586 ]]

参考文献

http://wiki.scipy.org/Tentati...

Sheppard K. Introduction to Python for econometrics, statistics and data analysis. Self-published, University of Oxford, version, 2012, 2.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/45210.html

相关文章

  • 编程界的“头牌”名媛:Python,14个与数据科学的“暧昧情事”

    摘要:安装安装用于数据科学的的最佳方法是使用发行版。但这只是展示了构建数据科学问题的不同方式中的机器学习这是一个重要的主题,机器学习正在风靡世界,是数据科学家工作的重要组成部分。 作为编程界的头牌名媛,Python平易近人的态度和精明婉约的灵动深得各个大佬欢心。比如:人工智能、web开发、爬虫、系统运维、数据分析与计算等等。这几位风流多金的行业精英随便哪个都能逆转未来。 本文为你精心准备了一...

    Labradors 评论0 收藏0
  • Python数据分析

    摘要:从本博客开始,将系统的学习的数据分析的六大模块,有关的基础知识,可以看我的博客。专为进行严格的数字处理而产生。在实现一个程序之前,值得检查下所需的数据处理方式是否已经在中存在了。积分六官网为了解决数据分析而创建的库。 从本博客开始,将系统的学习Python的数据分析的六大模块numpy、scipy、matplotlib、pandas、scikit-learn、keras,有关Pytho...

    Shimmer 评论0 收藏0
  • Python开发指南 托管Hadoop集群 UHadoop

    摘要:开发指南开发指南开发指南如果使用进行机器学习方面的数据分析,需要在集群上安装一些依赖包。以版本为例,安装方法如下是一款专为科学和工程设计的工具包。以版本为例,安装方法如下是下,专门面向机器学习的工具包。 developer/pythondev.mdPython开发指南如果使用pyspark进行机器学习方面的数据分析,需要在集群上安装一些python依赖包。这里将介绍常用的几个依赖包的安装方法...

    ernest.wang 评论0 收藏2969
  • 15个Python库,让你学习数据科学更轻松

    摘要:在本节中,我们将看到一些最流行和最常用的库,用于机器学习和深度学习是用于数据挖掘,分析和机器学习的最流行的库。愿码提示网址是一个基于的框架,用于使用多个或进行有效的机器学习和深度学习。 showImg(https://segmentfault.com/img/remote/1460000018961827?w=999&h=562); 来源 | 愿码(ChainDesk.CN)内容编辑...

    W4n9Hu1 评论0 收藏0
  • Python学习利器——我的小白 Anaconda安装之路

    摘要:学习利器我的小白安装之路序易用,但用好却不易,其中比较头疼的就是包管理和不同版本的问题,特别是当你使用的时候。另外值得一提的是,并不仅仅管理的工具包,它也能安装非的包。 Python学习利器——我的小白 Anaconda安装之路 序 Python易用,但用好却不易,其中比较头疼的就是包管理和Python不同版本的问题,特别是当你使用Windows的时候。为了解决这些问题,有不少发行版的...

    余学文 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<