Python数据分析之Numpy

数学建模自用

Numpy

NumPy是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,Numpy的一个重要特性是它的数组计算

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

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

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

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

数组上的数学操作

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

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

使用列表生成式的正确方法:

[x+1 for x in a]

[2, 3, 4, 5]

两个数组不能直接对应元素相加,与另一个数组相加,得到对应元素相加的结果:

b = [2,3,4,5]
a+b #并不是我们想要的结果

[1, 2, 3, 4, 2, 3, 4, 5](只是将两个数组合并)

正确的使用列表的方法:

[x+y for(x,y) in zip(a,b)]  #都需要利用到列表生成式

[3, 5, 7, 9]

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

如果我们使用Numpy,就会变得特别简单

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

array([1, 2, 3, 4])

a+1

array([2, 3, 4, 5])

a*2

array([2, 4, 6, 8])

b = np.array([2,3,4,5])
a + b

array([3, 5, 7, 9])

产生数组

从列表产生数组:

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

array([0, 1, 2, 3])

直接从列表传入:

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

array([1, 2, 3, 4])

生成全0数组:

np.zeros(5) #括号内传个数,默认浮点数

array([0., 0., 0., 0., 0.])

生成全1的数组:

np.ones(5) #括号内传个数,默认浮点数

array([1., 1., 1., 1., 1.])

使用dtype指定类型

np.ones(5,dtype="int") #可以自己指定类型,np.zeros函数同理

array([1, 1, 1, 1, 1])

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

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

array([1, 2, 3, 4])

a.fill(5) #让数组中的每一个元素都等于5
a

array([5, 5, 5, 5])

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

a.fill(2.5) 
a

array([2, 2, 2, 2]) (自动向下取整)

a = a.astype("float") #强制类型转换
a.fill(2.5)
a

array([2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5])

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

生成整数序列:

a = np.arange(1,10) #左闭右开区间,和range的使用方式同理
a

array([1, 2, 3, 4, 5, 6, 7, 8, 9])

生成等差数列:

a = np.linspace(1,10,21) #右边是包括在里面的,从a-b一共c个数的等差数列,其实np.arange好像也可以做...
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. ])

生成随机数

np.random.rand(10) #随机生成10个0到1的随机数

array([4.40869635e-04, 4.76388281e-01, 3.21620300e-03, 5.95847302e-01,6.31331331e-01, 4.94290308e-01, 9.78744667e-01, 9.20395355e-01,5.49642939e-01, 3.76350679e-02])

np.random.randn(10) #标准正态分布

array([-0.2155953 , -1.25507012, -0.55256054, 0.67047819, -0.94268625,-0.67406865, 0.37241395, 0.16134841, 0.04083109, -0.39151234])

np.random.randint(1,20,10) #生成随机整数,从1-20中随机10个

array([16, 13, 15, 8, 9, 4, 8, 1, 12, 14])

数组属性

查看类型:

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(表示a是一个n维数组)

查看数组中的数据类型:

a.dtype #元素的类型

dtype(‘float64’)(表示数组中的元素是整型)

查看形状,会返回一个元组,每个元素代表这一维的元素数目:

a.shape #21个元素

(21,)

或者使用:

np.shape(a)

(21,)

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

a.size

21

查看数组的维度(dim):

a.ndim

1

索引和切片

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

索引第一个元素(从0开始):

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

0

修改第一个元素的值

a[0] = 10
a

array([10, 1, 2, 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])

省略参数:

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])

可以这样计算每天的票房:

ob2 = ob[1:]-ob[:-1]
ob2

array([ 800, 440, 1210, 1550])

多维数组及其属性

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

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

array([[ 0, 1, 2, 3],
[10, 11, 12, 13]])

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

查看形状:

a.shape

(2, 4) (二行四列)

查看总的元素个数:

a.size

8

查看维数:

a.ndim

2

多维数组索引

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

a

array([[ 0, 1, 2, 3],
[10, 11, 12, 13]])

a[1,3]

-1 (第一行第三列的元素)

其中,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]

array([ 1, 11])

多维数组切片

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

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[0,3:5]

array([3, 4])

得到最后两行的最后两列:

a[4:,4:]

array([[44, 45],
[54, 55]])

得到第三列:

a[:,2]

array([ 2, 12, 22, 32, 42, 52])

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

[lower:upper:step]

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

a[2::2,::2]

array([[20, 22, 24],
[40, 42, 44]])

切片是引用

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

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

[2 3]

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

b[0] = 10
a

array([ 0, 1, 10, 3, 4])

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

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])

花式索引

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

一维花式索引

与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])

二维花式索引

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

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])

与切片不同,花式索引返回的是原对象的一个复制而不是引用。

“不完全”索引

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

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]])

where语句

where(array)

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

一维数组

先看一维的例子,判断数组中的元素是不是大于10:

a = np.array([0,12,5,20])
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,intint跟C语言中long一样大
无符号整型uint8,uint16,uint32,uint64,uint128,uintuint跟C语言中的unsigned long一样大
浮点数float16,float32,float默认为双精度float64,longfloat精度大小与系统有关
复数complex64,complex128,complex,longcomplex默认为complex128,即实部虚部都为双精度
字符串string,unicode可以使用dtype=S4表示一个4字节字符串的数组
对象object数组中可以使用任意值
时间datetime64,timedelta64

类型转换

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

array([ 1.5, -3. ])

asarray 函数

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

array([1., 2., 3.])

astype方法

astype 方法返回一个新数组:

a = np.array([1,2,3])
a.astype(float)

array([1., 2., 3.])

a #a本身并没有发生变化--拷贝

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])

数组排序

sort函数
np.sort(mv_num)

array([ 42995, 157074, 159302, 284652, 306904, 327855, 478523, 580897,
662552, 692795])

mv_num #sort不改变原来数组

array([692795, 42995, 327855, 580897, 478523, 157074, 306904, 662552,
284652, 159302])

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]]

‘肖申克的救赎’

求和

np.sum(mv_num)

3693549

mv_num.sum()

3693549

最大值
np.max(mv_length)

195

mv_length.max()

195

最小值
np.min(mv_score)

9.3

mv_score.min()

9.3

均值

np.mean(mv_length)

141.0

mv_length.mean()

141.0

标准差

np.std(mv_length)

33.713498780162226

mv_length.std()

33.713498780162226

相关系数矩阵

np.cov(mv_score,mv_length)

array([[9.88888889e-03, 4.55555556e-01],
[4.55555556e-01, 1.26288889e+03]])

4.多维数组操作

数组形状

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])

转置

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]])

数组连接

有时候我们需要将不同的数组按照一定的顺序连接起来:
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))
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.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,返回真,逻辑与
  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值