目录
Pandas与Numpy
Numpy
1、numpy 属性
2、Numpy的创建array
3、Numpy的基础运算
3、索引数
4、原地与非原地
5、Numpy中的切片与List的切片
6、二维数组的操作
Pandas使用
1、简单基本使用
2、索引
3、apply使用
4、axis参数
5、分组
6、向量运算
矩阵相乘复习
Pandas与Numpy
相同之处:
不同之处:Pandas拥有Numpy一些没有的方法,例如describe函数。其主要区别是:Numpy就像增强版的List,而Pandas就像列表和字典的合集,Pandas有索引。
Numpy
默认使用Anaconda
集成包环境开发。
1、numpy 属性
几种numpy的属性:
-
ndim
:维度
-
shape
:行数和列数
-
size
:元素个数
使用numpy
首先要导入模块
1 | import numpy as np #为了方便使用numpy 采用np简写 |
列表转化为矩阵:
1 2 3 4 5 6 | array = np. array ([[1,2,3],[2,3,4]]) #列表转化为矩阵 print ( array ) "" " array ([[1, 2, 3], [2, 3, 4]]) "" " |
完整代码运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # -*- coding:utf-8 -*- "" " @author: Corwien @file: np_attr.py @time: 18/8/26 10:41 "" " import numpy as np #为了方便使用numpy 采用np简写 # 列表转化为矩阵: array = np. array ([[1, 2, 3], [4, 5, 6]]) # 列表转化为矩阵 print ( array ) |
打印输出:
numpy 的几种属性
接着我们看看这几种属性的结果:
1 2 3 4 5 6 7 8 | print ( 'number of dim:' , array .ndim) # 维度 # number of dim: 2 print ( 'shape :' , array .shape) # 行数和列数 # shape : (2, 3) print ( 'size:' , array .size) # 元素个数 # size: 6 |
1 2 3 4 5 | import numpy as np #创建Numpy p1 = np.array([ 1 , 2 , 3 ]) print p1 print p1.dtype |
1 2 | #求平均值 print p1.mean() |
1 2 3 4 | #求和、求最大值、求最小值 print p1. sum () print p1. max () print p1. min () |
2、Numpy的创建array
关键字
-
array
:创建数组
-
dtype
:指定数据类型
-
zeros
:创建数据全为0
-
ones
:创建数据全为1
-
empty
:创建数据接近0
-
arrange
:按指定范围创建数据
-
linspace
:创建线段
创建数组
1 2 3 | a = np. array ([2,23,4]) # list 1d print (a) # [2 23 4] |
指定数据dtype
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | a = np. array ([2,23,4],dtype=np.int) print (a.dtype) # int 64 a = np. array ([2,23,4],dtype=np.int32) print (a.dtype) # int32 a = np. array ([2,23,4],dtype=np.float) print (a.dtype) # float64 a = np. array ([2,23,4],dtype=np.float32) print (a.dtype) # float32 |
创建特定数据
1 2 3 4 5 6 | a = np. array ([[2,23,4],[2,32,4]]) # 2d 矩阵 2行3列 print (a) "" " [[ 2 23 4] [ 2 32 4]] "" " |
创建全零数组
1 2 3 4 5 6 | a = np.zeros((3,4)) # 数据全为0,3行4列 "" " array ([[ 0., 0., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]) "" " |
创建全一数组, 同时也能指定这些特定数据的 dtype
:
1 2 3 4 5 6 | a = np.ones((3,4),dtype = np.int) # 数据为1,3行4列 "" " array ([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]) "" " |
创建全空数组, 其实每个值都是接近于零的数:
1 2 3 4 5 6 7 8 9 | a = np. empty ((3,4)) # 数据为 empty ,3行4列 "" " array ([[ 0.00000000e+000, 4.94065646e-324, 9.88131292e-324, 1.48219694e-323], [ 1.97626258e-323, 2.47032823e-323, 2.96439388e-323, 3.45845952e-323], [ 3.95252517e-323, 4.44659081e-323, 4.94065646e-323, 5.43472210e-323]]) "" " |
用 arange
创建连续数组:
1 2 3 4 | a = np.arange(10,20,2) # 10-19 的数据,2步长 "" " array ([10, 12, 14, 16, 18]) "" " |
使用 reshape
改变数据的形状
1 2 3 4 5 6 7 8 9 | # a = np.arange(12) # [ 0 1 2 3 4 5 6 7 8 9 10 11] a = np.arange(12).reshape((3,4)) # 3行4列,0到11 "" " array ([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) "" " |
用 linspace
创建线段型数据:
1 2 3 4 5 6 7 8 | a = np.linspace(1,10,20) # 开始端1,结束端10,且分割成20个数据,生成线段 "" " array ([ 1. , 1.47368421, 1.94736842, 2.42105263, 2.89473684, 3.36842105, 3.84210526, 4.31578947, 4.78947368, 5.26315789, 5.73684211, 6.21052632, 6.68421053, 7.15789474, 7.63157895, 8.10526316, 8.57894737, 9.05263158, 9.52631579, 10. ]) "" " |
同样也能进行 reshape
工作:
1 2 3 4 5 6 7 8 | a = np.linspace(1,10,20).reshape((5,4)) # 更改shape "" " array ([[ 1. , 1.47368421, 1.94736842, 2.42105263], [ 2.89473684, 3.36842105, 3.84210526, 4.31578947], [ 4.78947368, 5.26315789, 5.73684211, 6.21052632], [ 6.68421053, 7.15789474, 7.63157895, 8.10526316], [ 8.57894737, 9.05263158, 9.52631579, 10. ]]) "" " |
3、Numpy的基础运算
让我们从一个脚本开始了解相应的计算以及表示形式
1 2 3 4 5 6 7 8 9 10 11 12 | # -*- coding:utf-8 -*- "" " @author: Corwien @file: np_yunsuan.py @time: 18/8/26 23:37 "" " import numpy as np a = np. array ([10, 20, 30, 40]) # array ([10, 20, 30, 40]) b = np.arange(4) # array ([0, 1, 2, 3]) |
numpy 的几种基本运算
上述代码中的 a
和 b
是两个属性为 array 也就是矩阵的变量
,而且二者都是1行4列的矩阵, 其中b矩阵中的元素分别是从0到3。 如果我们想要求两个矩阵之间的减法,你可以尝试着输入:
1 | c=a-b # array ([10, 19, 28, 37]) |
通过执行上述脚本,将会得到对应元素相减的结果,即[10,19,28,37]
。 同理,矩阵对应元素的相加和相乘也可以用类似的方式表示:
1 2 | c=a+b # array ([10, 21, 32, 43]) c=a*b # array ([ 0, 20, 60, 120]) |
Numpy中具有很多的数学函数工具,比如三角函数等,当我们需要对矩阵中每一项元素进行函数运算时,可以很简便的调用它们(以sin
函数为例):
1 2 | c=10*np.sin(a) # array ([-5.44021111, 9.12945251, -9.88031624, 7.4511316 ]) |
上述运算均是建立在一维矩阵
,即只有一行的矩阵上面的计算,如果我们想要对多行多维度的矩阵
进行操作,需要对开始的脚本进行一些修改:
1 2 3 4 5 6 7 8 9 10 | a=np. array ([[1,1],[0,1]]) b=np.arange(4).reshape((2,2)) print (a) # array ([[1, 1], # [0, 1]]) print (b) # array ([[0, 1], # [2, 3]]) |
此时构造出来的矩阵a和b便是2行2列的,其中 reshape
操作是对矩阵的形状进行重构, 其重构的形状便是括号中给出的数字。 稍显不同的是,Numpy中的矩阵乘法分为两种
, 其一是前文中的对应元素相乘,其二是标准的矩阵乘法运算,即对应行乘对应列得到相应元素:
1 2 3 | c_dot = np.dot(a,b) # array ([[2, 4], # [2, 3]]) |
除此之外还有另外的一种关于dot
的表示方法,即:
1 2 3 | c_dot_2 = a.dot(b) # array ([[2, 4], # [2, 3]]) |
下面我们将重新定义一个脚本, 来看看关于 sum()
, min()
, max()
的使用:
1 2 3 4 5 | import numpy as np a=np.random.random((2,4)) print (a) # array ([[ 0.94692159, 0.20821798, 0.35339414, 0.2805278 ], # [ 0.04836775, 0.04023552, 0.44091941, 0.21665268]]) |
因为是随机生成数字, 所以你的结果可能会不一样. 在第二行中对a
的操作是令a
中生成一个2行4列的矩阵,且每一元素均是来自从0到1的随机数。 在这个随机生成的矩阵中,我们可以对元素进行求和以及寻找极值的操作,具体如下:
1 2 3 | np.sum(a) # 4.4043622002745959 np.min(a) # 0.23651223533671784 np.max(a) # 0.90438450240606416 |
对应的便是对矩阵中所有元素进行求和,寻找最小值,寻找最大值的操作。 可以通过print()
函数对相应值进行打印检验。
如果你需要对行或者列进行查找运算,就需要在上述代码中为 axis
进行赋值。 当axis的值为0的时候,将会以列作为查找单元, 当axis的值为1的时候,将会以行作为查找单元。
为了更加清晰,在刚才的例子中我们继续进行查找:
1 2 3 4 5 6 7 8 9 10 11 12 | print ( "a =" ,a) # a = [[ 0.23651224 0.41900661 0.84869417 0.46456022] # [ 0.60771087 0.9043845 0.36603285 0.55746074]] print ( "sum =" ,np.sum(a,axis=1)) # sum = [ 1.96877324 2.43558896] print ( "min =" ,np.min(a,axis=0)) # min = [ 0.23651224 0.41900661 0.36603285 0.46456022] print ( "max =" ,np.max(a,axis=1)) # max = [ 0.84869417 0.9043845 ] |
1 2 | p1 = np.array([ 1 , 2 , 3 ]) p2 = np.array([ 2 , 5 , 7 ]) |
1 2 | #向量相加,各个元素相加 print p1 + p2 |
1 2 | #向量乘以1个常数 print p1 * 2 |
1 2 | #向量相乘,各个元素之间做运算 print p1 * p2 |
1 2 | #向量与一个常数比较 print p1 > 2 |
4、索引数
1 2 | a = np.array([ 1 , 2 , 3 , 4 , 5 ]) print a |
1 | [False False True True True] |
a[b]中,只会保留a中所对应的b位置为True的元素
5、Numpy中的切片与List的切片
1 2 3 4 5 | l1 = [ 1 , 2 , 3 , 5 ] l2 = l1[ 0 : 2 ] l2[ 0 ] = 5 print l2 print l1 |
1 2 3 4 5 | p1 = np.array([ 1 , 2 , 3 , 5 ]) p2 = p1[ 0 : 2 ] p2[ 0 ] = 5 print p1 print p2 |
从上可知,List中改变切片中的元素,不会影响原来的数组;而Numpy改变切片中的元素,原来的数组也跟着变了。这是因为:Numpy的切片编程不会创建一个新数组出来,当修改对应的切片也会更改原始的数组数据。这样的机制,可以让Numpy比原生数组操作更快,但编程时需要注意。
6、二维数组的操作
1 2 3 | p1 = np.array([[ 1 , 2 , 3 ], [ 7 , 8 , 9 ], [ 2 , 4 , 5 ]]) #获取其中一维数组 print p1[ 0 ] |
1 2 3 | #获取其中一个元素,注意它可以是p1[0, 1],也可以p1[0][1] print p1[ 0 , 1 ] print p1[ 0 ][ 1 ] |
1 2 | #求和是求所有元素的和 print p1. sum () |
但,当设置axis参数时,当设置为0时,是计算每一列的结果,然后返回一个一维数组;若是设置为1时,则是计算每一行的结果,然后返回一维数组。对于二维数组,Numpy中很多函数都可以设置axis参数。
1 2 | #获取每一列的结果 print p1. sum (axis = 0 ) |
1 2 | #获取每一行的结果 print p1. sum (axis = 1 ) |
1 2 | #mean函数也可以设置axis print p1.mean(axis = 0 ) |
1 | [ 3.33333333 4.66666667 5.66666667] |
Pandas使用
Pandas有两种结构,分别是Series和DataFrame。其中Series拥有Numpy的所有功能,可以认为是简单的一维数组;而DataFrame是将多个Series按列合并而成的二维数据结构,每一列单独取出来是一个Series。
咱们主要梳理下Numpy没有的功能:
1、简单基本使用
1 2 3 | import pandas as pd pd1 = pd.Series([ 1 , 2 , 3 ]) print pd1 |
1 2 3 4 | 0 1 1 2 2 3 dtype: int64 |
1 2 3 | #也可以求和和标准偏差 print pd1. sum () print pd1.std() |
2、索引
(1)Series中的索引
1 2 3 4 5 | p1 = pd.Series( [ 1 , 2 , 3 ], index = [ 'a' , 'b' , 'c' ] ) print p1 |
1 2 3 4 | a 1 b 2 c 3 dtype: int64 |
(2)DataFrame数组
1 2 3 4 5 | p1 = pd.DataFrame({ 'name' : [ 'Jack' , 'Lucy' , 'Coke' ], 'age' : [ 18 , 19 , 21 ] }) print p1 |
1 2 3 4 | age name 0 18 Jack 1 19 Lucy 2 21 Coke |
1 2 | #获取name一列 print p1[ 'name' ] |
1 2 3 4 | 0 Jack 1 Lucy 2 Coke Name: name, dtype: object |
1 2 | #获取姓名的第一个 print p1[ 'name' ][ 0 ] |
1 2 | #使用p1[0]不能获取第一行,但是可以使用iloc print p1.iloc[ 0 ] |
1 2 3 | age 18 name Jack Name: 0, dtype: object |
总结:
-
获取一列使用p1[‘name']这种索引
-
获取一行使用p1.iloc[0]
3、apply使用
apply可以操作Pandas里面的元素,当库里面没用对应的方法时,可以通过apply来进行封装
1 2 3 | def func(value): return value * 3 pd1 = pd.Series([ 1 , 2 , 5 ]) |
1 2 3 4 | 0 3 1 6 2 15 dtype: int64 |
同样可以在DataFrame上使用:
1 2 3 4 5 | pd2 = pd.DataFrame({ 'name' : [ 'Jack' , 'Lucy' , 'Coke' ], 'age' : [ 18 , 19 , 21 ] }) print pd2. apply (func) |
1 2 3 4 | age name 0 54 JackJackJack 1 57 LucyLucyLucy 2 63 CokeCokeCoke |
4、axis参数
Pandas设置axis时,与Numpy有点区别:
1 2 3 4 | pd2 = pd.DataFrame({ 'weight' : [ 120 , 130 , 150 ], 'age' : [ 18 , 19 , 21 ] }) |
1 2 3 4 | 0 138 1 149 2 171 dtype: int64 |
1 2 | #计算每一行的值 print pd2. sum (axis = 'columns' ) |
1 2 3 4 | 0 138 1 149 2 171 dtype: int64 |
1 2 | #计算每一列的值 print pd2. sum (axis = 'index' ) |
1 2 3 | age 58 weight 400 dtype: int64 |
5、分组
1 2 3 4 5 6 | pd2 = pd.DataFrame({ 'name' : [ 'Jack' , 'Lucy' , 'Coke' , 'Pol' , 'Tude' ], 'age' : [ 18 , 19 , 21 , 21 , 19 ] }) #以年龄分组 print pd2.groupby( 'age' ).groups |
1 | {18: Int64Index([0], dtype='int64'), 19: Int64Index([1, 4], dtype='int64'), 21: Int64Index([2, 3], dtype='int64')} |
6、向量运算
需要注意的是,索引数组相加时,对应的索引相加
1 2 3 4 5 6 7 8 | pd1 = pd.Series( [ 1 , 2 , 3 ], index = [ 'a' , 'b' , 'c' ] ) pd2 = pd.Series( [ 1 , 2 , 3 ], index = [ 'a' , 'c' , 'd' ] ) |
1 2 3 4 5 | a 2.0 b NaN c 5.0 d NaN dtype: float64 |
出现了NAN值,如果我们期望NAN不出现,如何处理?使用add函数,并设置fill_value参数
1 | print pd1.add(pd2, fill_value = 0 ) |
1 2 3 4 5 | a 2.0 b 2.0 c 5.0 d 3.0 dtype: float64 |
矩阵相乘复习
矩阵相乘,两个矩阵只有当左边的矩阵的列数等于右边矩阵的行数时,两个矩阵才可以进行矩阵的乘法运算
。 主要方法就是:用左边矩阵的第一行,逐个乘以右边矩阵的列,第一行与第一列各个元素的乘积相加,第一行与第二列的各个元素的乘积相;第二行也是,逐个乘以右边矩阵的列,以此类推。
1 2 3 4 5 6 7 8 9 10 11 | 矩阵A=1 2 3 4 5 6 7 8 0 矩阵B=1 2 1 1 1 2 2 1 1 |
求AB
最后的得出结果是
1 2 3 4 5 | AB=9 7 8 21 19 20 15 22 23 |
使用numpy计算:
1 2 3 4 5 | e = np. array ([[1, 2, 3], [4, 5, 6], [7, 8, 0]]) f = np. array ([[1, 2, 1], [1, 1, 2], [2, 1, 1]]) res_dot = np.dot(e, f) print res_dot |
打印结果:
1 2 3 | [[ 9 7 8] [21 19 20] [15 22 23]] |