Python 数据分析之Numpy

Python 数据分析之Numpy

Python有着大量功能强大的第三方库。这些第三方库可以大大地扩充Python的功能,我们在实际使用中往往也离不开这些第三方库。

NumPy是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多。NumPy(Numeric Python)提供了许多高级的数值编程工具。Numpy的一个重要特性是它的数组计算,是我们做数据分析必不可少的一个包。

导入python库使用关键字import,后面可以自定义库的简称,但是一般都将Numpy命名为np,pandas命名为pd。

使用前一定要先导入Numpy包,导入的方法有以下几种:

import numpy
import numpy as np  # 推荐写法
from numpy import * # 不是很建议这种写法,因为不用加前缀的话有可能会与其他函数名称起冲突,因而报错

1. Numpy 的数组对象及其索引

1.1 数组上的数学操作

假设我们想将列表中的每个元素增加1,但列表不支持这样的操作:

a = [1,2,3,4]
#a+1   # 报错

列表中的每个元素增加1的正确写法:

a = [1,2,3,4]
[x+1 for x in a]
--------------------
输出
[2, 3, 4, 5]

与另一个数组相加,得到对应元素相加的结果:

a = [1,2,3,4]
b = [2,3,4,5]
a+b  # 并不是我们想要的结果
--------------------
输出
[1, 2, 3, 4, 2, 3, 4, 5]
# 需要利用到列表生成式
[x+y for(x,y) in zip(a,b)]  # zip 打包命令,将a b组成一个数对
--------------------
输出
[3, 5, 7, 9]

这样的操作比较麻烦,而且在数据量特别大的时候会非常耗时间。

如果我们使用Numpy,就会变得特别简单
a = np.array([1,2,3,4]) # 初始化一个numpy数组
a
--------------------
输出
array([1, 2, 3, 4])

每个元素增加1

a+1
--------------------
输出
array([2, 3, 4, 5])

每个元素乘2

a*2
--------------------
输出
array([2, 4, 6, 8])

a和b相加

a = np.array([1,2,3,4])
b = np.array([2,3,4,5])
a + b
--------------------
输出
array([3, 5, 7, 9])

1.2 产生数组

1.2.1 从列表产生数组

l = [0,1,2,3]
a = np.array(l)
a
--------------------
输出
array([0, 1, 2, 3])

1.2.2 从列表传入

a = np.array([1,2,3,4])
a
--------------------
输出
array([1, 2, 3, 4])

1.2.3 生成全0数组

np.zeros(5)  # 括号内传个数,默认浮点数
--------------------
输出
array([0., 0., 0., 0., 0.])

1.2.4 生成全1的数组

np.ones(5)  # 括号内传个数,默认浮点数
--------------------
输出
array([1., 1., 1., 1., 1.])
np.ones(5,dtype="bool")  # 可以自己指定类型,np.zeros函数同理
--------------------
输出
array([ True,  True,  True,  True,  True])
np.ones(5,dtype="int")  # 可以自己指定类型,np.zeros函数同理
--------------------
输出
array([1, 1, 1, 1, 1])

1.2.5 可以使用 fill 方法将数组设为指定值

a = np.array([1,2,3,4])
a
--------------------
输出
array([1, 2, 3, 4])
a.fill(5)  # 让数组中的每一个元素都等于5
a
--------------------
输出
array([5, 5, 5, 5])

与列表不同,数组中要求所有元素的 dtype 是一样的,如果传入参数的类型与数组类型不一样,需要按照已有的类型进行转换。

a = np.array([1,2,3,4])
a.fill(2.5)  # 根据已有类型来产生数组
a
--------------------
输出
array([2, 2, 2, 2])

强制类型转换

a = np.array([1,2,3,4])
a = a.astype("float") #强制类型转换
a.fill(2.5)
a
--------------------
输出
array([2.5, 2.5, 2.5, 2.5])

还可以使用一些特定的方法生成特殊的数组

1.2.6 生成整数序列

a = np.arange(1,10)  # 左闭右开区间,和range的使用方式同理
a
--------------------
输出
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
a = np.arange(1,10)  # 左闭右开区间,和range的使用方式同理
a
--------------------
输出
array([1, 3, 5, 7, 9])

1.2.7 生成等差数列

a = np.linspace(1,10,21)  # 右边是包括在里面的,从a到b一共c个数的等差数列
a
--------------------
输出
array([ 1.  ,  1.45,  1.9 ,  2.35,  2.8 ,  3.25,  3.7 ,  4.15,  4.6 ,
        5.05,  5.5 ,  5.95,  6.4 ,  6.85,  7.3 ,  7.75,  8.2 ,  8.65,
        9.1 ,  9.55, 10.  ])

1.2.8 生成随机数

np.random.rand(10) # rand括号里为生成随机数的个数
--------------------
输出
array([0.75456867, 0.7810148 , 0.57683122, 0.18786396, 0.53159524,
       0.20403062, 0.3119359 , 0.424893  , 0.25618697, 0.08767851])

服从标准正态分布

np.random.randn(10)  # 标准正态分布
--------------------
输出
array([ 1.05865726,  0.34513619,  0.35855723, -0.06145859,  0.04337155,
        0.70850382, -1.29324883, -1.90938997, -2.53480652,  2.44232185])

生成随机整数,从1-20中随机10个

np.random.randint(1,20,10) #生成随机整数,从1到20中随机10个
--------------------
输出
array([ 7, 14, 14, 16, 11, 13,  1, 12, 10,  5])

1.3 数组属性

1.3.1 查看类型

a
--------------------
输出
array([ 1.  ,  1.45,  1.9 ,  2.35,  2.8 ,  3.25,  3.7 ,  4.15,  4.6 ,
        5.05,  5.5 ,  5.95,  6.4 ,  6.85,  7.3 ,  7.75,  8.2 ,  8.65,
        9.1 ,  9.55, 10.  ])
type(a)
--------------------
输出
numpy.ndarray

1.3.2 查看数组中的数据类型

a.dtype
--------------------
输出
dtype('float64')

1.3.3 查看形状

会返回一个元组,每个元素代表这一维的元素数目

a.shape
--------------------
输出
(21,)

或者使用

np.shape(a)
--------------------
输出
(21,)

1.3.4 要看数组里面元素的个数

a.size
--------------------
输出
21

1.3.5 查看数组的维度

a.ndim
--------------------
输出
1

1.4 索引和切片

和列表相似,数组也支持索引和切片操作

1.4.1 索引第一个元素

a = np.array([0,1,2,3])
a[0]
--------------------
输出
0

1.4.2 修改第一个元素的值

a[0] = 10
a
--------------------
输出
array([10,  1,  2,  3])

1.4.3 切片,支持负索引

a = np.array([11,12,13,14,15])
a[1:3]  # 左闭右开,从0开始算
--------------------
输出
array([12, 13])
a[1:-2]  # 等价于a[1:3]
--------------------
输出
array([12, 13])
a[-4:3]  # 仍然等价a[1:3]
--------------------
输出
array([12, 13])

1.4.4 省略参数

a = np.array([11,12,13,14,15])
a[-2:]  # 从倒数第2个取到底
--------------------
输出
array([14, 15])
a[::2]  # 从头取到尾,间隔2
--------------------
输出
array([11, 13, 15])

例:假设我们记录一部电影的累计票房

ob = np.array([21000,21800,22240,23450,25000])
ob
--------------------
输出
array([21000, 21800, 22240, 23450, 25000])

可以这样计算每天的票房

# 21800,22240,23450,25000
# -
# 21000,21800,22240,23450
ob2 = ob[1:]-ob[:-1]
ob2
--------------------
输出
array([ 800,  440, 1210, 1550])

1.5 多维数组及其属性

1.5.1 多维数组基本操作

(1) 生成多维数组

array还可以用来生成多维数组

a = np.array([[0,1,2,3],[10,11,12,13]])
a
--------------------
输出
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13]])

事实上我们传入的是一个以列表为元素的列表,最终得到一个二维数组

(2) 查看形状
a.shape
--------------------
输出
(2, 4)  # 2行4列
(3) 查看总的元素个数
a.size
--------------------
输出
8
(4) 查看维数
a.ndim
--------------------
输出
2

1.5.2 多维数组索引

对于二维数组,可以传入两个数字来索引

a = np.array([[0,1,2,3],
              [10,11,12,13]])
a[1,3]
--------------------
输出
13

其中,1是行索引,3是列索引,中间用逗号隔开。事实上,Python会将它们看成一个元组(1,3),然后按照顺序进行对应。

可以利用索引给它赋值

a[1,3] = -1
a
--------------------
输出
array([[ 0,  1,  2,  3],
       [10, 11, 12, -1]])

事实上,我们还可以使用单个索引来索引一整行内容

a[1]
--------------------
输出
array([10, 11, 12, -1])

Python会将这单个元组当成对第一维的索引,然后返回对应列的内容

a[:,1] # 第二列的内容    1 表示第二列
--------------------
输出
array([ 1, 11])

1.5.3 多维数组切片

多维数组,也支持切片操作

a = np.array([[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
--------------------
输出
array([[ 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]])

得到第一行的第4和第5两个元素

a[ a : b , c : d ]

逗号前为行,逗号后为列

a : b 为 a到b;c : d 为 c到d

a[0,3:5] # 0为行索引;3到5取到第四第五个元素
--------------------
输出
array([3, 4])

得到最后两行的最后两列

a[4:,4:]
--------------------
输出
array([[44, 45],
       [54, 55]])

得到第三列

a[:,2]
--------------------
输出
array([ 2, 12, 22, 32, 42, 52])
a[:,2:3]
--------------------
输出
array([[ 2],
       [12],
       [22],
       [32],
       [42],
       [52]])

每一维都支持切片的规则,包括负索引,省略

[lower:upper:step]

例如,取出3,5行的奇数列

a[2::2,::2]
# 行:从第二行开始取,取到最后,步长为2。即 2::2
# 列:取整列,奇数列,步长取2
--------------------
输出
array([[20, 22, 24],
       [40, 42, 44]])

1.5.4 切片是引用

切片在内存中使用的是引用机制

a = np.array([0,1,2,3,4])
b = a[2:4]
print(b)
--------------------
输出
[2 3]
b[0] = 10
a
--------------------
输出
array([ 0,  1, 10,  3,  4])

引用机制意味着,Python并没有为b分配新的空间来存储它的值,而是让b指向了a所分配的内存空间,因此,改变b会改变a的值

而这种现象在列表中并不会出现

a = [1,2,3,4,5]
b = a[2:4]
b[0] = 10
print(a)
--------------------
输出
[1, 2, 3, 4, 5]

引用机制的好处:这样做的好处在于,对于很大的数组,不用大量复制多余的值,节约了空间。

引用机制的缺点:可能出现改变一个值改变另一个值的情况

一个解决方法是使用copy()方法产生一个复制,这个复制会申请新的内存

a = np.array([0,1,2,3,4])
b = a[2:4].copy()
b[0] = 10
a
--------------------
输出
array([0, 1, 2, 3, 4])

1.5.5 花式索引

切片只能支持连续或者等间隔的切片操作,要想实现任意位置的操作。需要使用花式索引 fancy slicing

(1) 一维花式索引

与range函数类似,我们可以使用arange函数来产生等差数组

a = np.arange(0,100,10)
a
--------------------
输出
array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])

花式索引需要指定索引位置

index = [1,2,-3]
y = a[index]
print(y)
--------------------
输出
[10 20 70]

还可以使用布尔数组来花式索引

mask = np.array([0,2,2,0,0,1,0,0,1,0],dtype = bool)
mask
--------------------
输出
array([False,  True,  True, False, False,  True, False, False,  True,
       False])

mask必须是布尔数组,长度必须和数组长度相等

a[mask]
--------------------
输出
array([10, 20, 50, 80])
(2) 二维花式索引

对于二维花式索引,我们需要给定行和列的值

a = np.array([[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
--------------------
输出
array([[ 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]])

返回的是一条次对角线上的5个值

a[(0,1,2,3,4),(1,2,3,4,5)]
--------------------
输出
array([ 1, 12, 23, 34, 45])

返回的是最后三行的1,3,5列

a[3:,[0,2,4]]
--------------------
输出
array([[30, 32, 34],
       [40, 42, 44],
       [50, 52, 54]])

也可以使用mask进行索引

mask = np.array([1,0,1,0,0,1],dtype = bool)
a[mask,2]
--------------------
输出
array([ 2, 22, 52])

1.5.6 “不完全”索引

只给定行索引的时候,返回整行

a = np.array([[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]])
y = a[:3]
y
--------------------
输出
array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25]])

这时候也可以使用花式索引取出第2,3,5行

con = np.array([0,1,1,0,1,0],dtype = bool)
a[con]
--------------------
输出
array([[10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [40, 41, 42, 43, 44, 45]])

1.5.7 where 语句

where(array)

where函数会返回所有非零元素的索引

(1) 一维数组

先看一维的例子

a = np.array([0,12,5,20])

判断数组中的元素是不是大于10

a>10
--------------------
输出
array([False,  True, False,  True])

数组中所有大于10的元素的索引位置

np.where(a>10)
--------------------
输出
(array([1, 3], dtype=int64),)

注意到where的返回值是一个元组。返回的是索引位置,索引[1,3]大于10的数

也可以直接用数组操作

a[a>10]
--------------------
输出
array([12, 20])
a[np.where(a>10)]
--------------------
输出
array([12, 20])

2. 数组类型

具体如下:

基本类型 可用的Numpy类型 备注
布尔型 bool 占一个字节
整型 int8,int16,int32,int64,int128,int int跟C语言中long一样大
无符号整型 uint8,uint16,uint32,uint64,uint128,uint uint跟C语言中的unsigned long一样大
浮点数 float16,float32,float 默认为双精度float64,longfloat精度大小与系统有关
复数 complex64,complex128,complex,longcomplex 默认为complex128,即实部虚部都为双精度
字符串 string,unicode 可以使用dtype=S4表示一个4字节字符串的数组
对象 object 数组中可以使用任意值
时间 datetime64,timedelta64

2.1 类型转换

a = np.array([1.5,-3],dtype = float)
a
--------------------
输出
array([ 1.5, -3. ])

2.2 asarray 函数

a = np.array([1,2,3])
np.asarray(a,dtype = float)
--------------------
输出
array([1., 2., 3.])

2.3 astype方法

astype 方法返回一个新数组

a = np.array([1,2,3])
a.astype(float)
--------------------
输出
array([1., 2., 3.])
a  # a本身并没有发生变化--拷贝
--------------------
输出
array([1, 2, 3])
a = np.array([1,2,3])
b=a.astype(float)  # 将a.astype赋值给b
b
--------------------
输出
array([1., 2., 3.])

3. 数组操作

我们以豆瓣10部高分电影为例

## 电影名称
mv_name = ["肖申克的救赎","控方证人","美丽人生","阿甘正传","霸王别姬","泰坦尼克号","辛德勒的名单","这个杀手不太冷","疯狂动物城","海豚湾"]
## 评分人数
mv_num = np.array([692795,42995,327855,580897,478523,157074,306904,662552,284652,159302])
##评分
mv_score = np.array([9.6,9.5,9.5,9.4,9.4,9.4,9.4,9.3,9.3,9.3])
##电影时长(分钟)
mv_length = np.array([142,116,116,142,171,194,195,133,109,92])

3.1 数组排序

(1) sort 函数

电影评分人数mv_num从小到大排序

np.sort(mv_num)
--------------------
输出
array([ 42995, 157074, 159302, 284652, 306904, 327855, 478523, 580897,
       662552, 692795])

sort不改变原来数组

mv_num  #sort不改变原来数组
--------------------
输出
array([692795,  42995, 327855, 580897, 478523, 157074, 306904, 662552,
       284652, 159302])
(2) argsort 函数

argsort 返回从小到大的排列在数组中的索引位置

order = np.argsort(mv_num)
order
--------------------
输出
array([1, 5, 9, 8, 6, 2, 4, 3, 7, 0], dtype=int64)
mv_name[order[0]]
--------------------
输出
'控方证人'
mv_name[order[-1]]
--------------------
输出
'肖申克的救赎'

3.2 计算

(1) 求和
np.sum(mv_num)
--------------------
输出
3693549
mv_num.sum()
--------------------
输出
3693549
(2) 最大值
np.max(mv_length)
--------------------
输出
195
mv_length.max()
--------------------
输出
195
(3) 最小值
np.min(mv_score)
--------------------
输出
9.3
mv_score.min()
--------------------
输出
9.3
(4) 均值
np.mean(mv_length)
--------------------
输出
141.0
mv_length.mean()
--------------------
输出
141.0
(5) 标准差
np.std(mv_length)
--------------------
输出
33.713498780162226
mv_length.std()
--------------------
输出
33.713498780162226
(6) 协方差矩阵
np.cov(mv_score,mv_length)
--------------------
输出
array([[9.88888889e-03, 4.55555556e-01],
       [4.55555556e-01, 1.26288889e+03]])

4. 多维数组操作

4.1 数组形状

a = np.arange(6)
a
--------------------
输出
array([0, 1, 2, 3, 4, 5])
a.shape=(2,3)
a
--------------------
输出
array([[0, 1, 2],
       [3, 4, 5]])
a.shape
--------------------
输出
(2, 3)

与之对应的方法是reshape,但它不会修改原来数组的值,而是返回一个新的数组

a = np.arange(6)
a
--------------------
输出
array([0, 1, 2, 3, 4, 5])
a.reshape(2,3)
--------------------
输出
array([[0, 1, 2],
       [3, 4, 5]])
a   # 没变
--------------------
输出
array([0, 1, 2, 3, 4, 5])

4.2 转置

a = a.reshape(2,3)
a
--------------------
输出
array([[0, 1, 2],
       [3, 4, 5]])
a.T  # 转置
--------------------
输出
array([[0, 3],
       [1, 4],
       [2, 5]])
a.transpose()   # 只要没赋值给本身,a的数值不会变换
--------------------
输出
array([[0, 3],
       [1, 4],
       [2, 5]])
a
--------------------
输出
array([[0, 1, 2],
       [3, 4, 5]])

4.3 数组连接

有时候我们需要将不同的数组按照一定的顺序连接起来:
concatenate((a0,a1,…,aN),axis = 0)

注意,这些数组要用()包括到一个元组中去。
除了给定的轴外,这些数组其他轴的长度必须是一样的。

x = np.array([[0,1,2],[10,11,12]])
y = np.array([[50,51,52],[60,61,62]])
print(x.shape)
print(y.shape)
--------------------
输出
(2, 3)
(2, 3)

默认沿着第一维进行连接

z = np.concatenate((x,y))  # axis默认为0,沿着列连接
z
--------------------
输出
array([[ 0,  1,  2],
       [10, 11, 12],
       [50, 51, 52],
       [60, 61, 62]])

沿着第二维进行连接

z = np.concatenate((x,y),axis = 1)
z
--------------------
输出
array([[ 0,  1,  2, 50, 51, 52],
       [10, 11, 12, 60, 61, 62]])

注意到这里x和y的形状是一样的,还可以将它们连接成三维的数组,但是concatenate不能提供这样的功能,不过可以这样

z = np.array((x,y))
z
--------------------
输出
array([[[ 0,  1,  2],
        [10, 11, 12]],

       [[50, 51, 52],
        [60, 61, 62]]])

事实上,Numpy提供了分别对应这三种情况的函数:

  • vstack 沿着第一维进行连接
  • hstack 沿着第二维进行连接
  • dstack 沿着第三维进行连接
np.vstack((x,y))
--------------------
输出
array([[ 0,  1,  2],
       [10, 11, 12],
       [50, 51, 52],
       [60, 61, 62]])
np.hstack((x,y))
--------------------
输出
array([[ 0,  1,  2, 50, 51, 52],
       [10, 11, 12, 60, 61, 62]])
np.dstack((x,y))
--------------------
输出
array([[[ 0, 50],
        [ 1, 51],
        [ 2, 52]],

       [[10, 60],
        [11, 61],
        [12, 62]]])

5. Numpy 内置函数

a = np.array([-1,2,3,-2])
np.abs(a)   # 绝对值
--------------------
输出
array([1, 2, 3, 2])
np.exp(a)   # 指数
--------------------
输出
array([ 0.36787944,  7.3890561 , 20.08553692,  0.13533528])
np.median(a)   # 中值
--------------------
输出
0.5
np.cumsum(a)   # 累积和
--------------------
输出
array([-1,  1,  4,  2], dtype=int32)

numpy的内置函数非常多,不需要死记

https://blog.csdn.net/nihaoxiaocui/article/details/51992860?locationNum=5&fps=1

6. 数组属性方法总结

调用方法 作用
1 基本属性
a.dtype 数组元素类型float32,uint8,…
a.shape 数组形状(m,n,o,…)
a.size 数组元素数
a.itemsize 每个元素占字节数
a.nbytes 所有元素占的字节
a.ndim 数组维度
- -
2 形状相关
a.flat 所有元素的迭代器
a.flatten() 返回一个1维数组的复制
a.ravel() 返回一个一维数组,高效
a.resize(new_size) 改变形状
a.swapaxes(axis1,axis2) 交换两个维度的位置
a.transpose(* axex) 交换所有维度的位置
a.T 转置,a.transpose()
a.squeeze() 去除所有长度为1的维度
- -
3 填充复制
a.copy() 返回数组的一个复制
a.fill(value) 将数组的元组设置为特定值
- -
4 转化
a.tolist() 将数组转化为列表
a.tostring() 转换为字符串
a.astype(dtype) 转换为指定类型
a.byteswap(False) 转换大小字节序
a.view(type_or_dtype) 生成一个使用相同内存,但使用不同的表示方法的数组
- -
5 查找排序
a.nonzero() 返回所有非零元素的索引
a.sort(axis=-1) 沿某个轴排序
a.argsort(axis=-1) 沿某个轴,返回按排序的索引
a.searchsorted(b) 返回将b中元素插入a后能保持有序的索引值
- -
6 元素数学操作
a.clip(low,high) 将数值限制在一定范围内
a.round(decimals=0) 近似到指定精度
a.cumsum(axis=None) 累加和
a.cumprod(axis=None) 累乘积
- -
7 约简操作
a.sum(axis=None) 求和
a.prod(axis=None) 求积
a.min(axis=None) 最小值
a.max(axis=None) 最大值
a.argmin(axis=None) 最小值索引
a.argmax(axis=None) 最大值索引
a.ptp(axis=None) 最大值减最小值
a.mean(axis=None) 平均值
a.std(axis=None) 标准差
a.var(axis=None) 方差
a.any(axis=None) 只要有一个不为0,返回真,逻辑或
a.all(axis=None) 所有都不为0,返回真,逻辑与

你可能感兴趣的:(python,数据分析,numpy,python,数据分析)