Numpy

Numpy是一个模块

序章:数组和矩阵的区别

• matrix是array的分支,matrix和array在很多时候都是通用的,用哪一个都一样;
• 如果两个可以通用,那就选择array,因为array更灵活,速度更快,很多人把二维的array也翻译成矩阵。
• 相同点:索引方式相同,都可以使用a[i][j],a[i,j]进行索引
• matrix(矩阵):具有相对简单的运算符号,比如两个matrix相乘(求内积),就是用符号*
• array(数组):两个一维数组相乘用*,对应元素相乘
由于Python:是先循环遍历再计算,Numpyi直接计算,计算数量越大越节省时间
一维数组相加:

1
2
3
4
5
6
import numpy as np
def 数组相加(n):
a=np.arange(1,n+1)**3
b=np.arange(1,n+1)**2
return a+b
print(数组相加(3))

一维数组相乘,若用sum(a*b)则可以把内部元素相加

1
2
3
4
5
6
mport numpy as np
def 数组相乘(n):
a=np.arange(1,n+1)**3
b=np.arange(1,n+1)**2
return a*b
print(数组相乘(3))

多维数组也可以看成矩阵,如果进行矩阵相乘,则需要用到np.dot(),如np.dot(arr.T,arr) 参考资料 Python/Numpy之矩阵/数组/列表转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
'''rand函数的作用就是从标准正态分布中返回一个或多个样本值,
这里返回2行3列共6个数的数组。标准正态分布俗称高斯分布,均值为0,方差为1的正态分布。'''
arr=np.random.rand(2,3)
b=np.dot(arr.T,arr)#把数组当成矩阵,对应元素相乘求内积 arr.T为arr的转置
#将数组转化成矩阵
arr_Matrix=np.mat(arr)#等同于arr Matrix=matrix(arr),mat是natrix的缩写
c=arr_Matrix.T*arr_Matrix#矩阵直接相乘
#将结果输出
print("arr:\n{}\ntype(arr):{}".format(arr,type(arr)))
print("数组(矩阵)乘积:\n",b)
print("arr_Matrix:\n{}\ntype(arr_Matrix):{}".format(arr_Matrix,type(arr_Matrix)))
print("矩阵乘积:\n",c)
#比较两者乘积是否相等
print("数组矩阵内积-矩阵乘积:\n",b==c)

创建数组

1.1 创建数组的方法

1
2
3
4
5
6
7
8
9
import numpy as np
a = np.array([1,2,3,4,5])
b = np.array(range(1,6))
c = np.arange(1,6)
print(a)
print(b)
print(c)
print(a.dtype) # int32或int64
print(type(a)) # <class 'numpy.ndarray'>

以上三种方法结果是一样的,注意一下输入结果是数组
array:将输入数据(可以是列表、元组、数组以及其它序列)转换为ndarray(Numpy数组),如不显示指明数据类型,将自动推断,默认复制所有输入数据。
arange:Python内建函数range的数组版,返回一个数组。
array的属性:
• shape:返回一个元组,表示 array的维度 [形状,几行几列] (2,3)两行三列,(2,2,3)两个两行三列
• ndim:返回一个数字,表示array的维度的数目
• size:返回一个数字,表示array中所有数据元素的数目
• dtype:返回array中元素的数据类型
使用arange创建数字序列:
np.arange([开始,]结束[,步长],dtype=None)
np.arange(5) 返回 array([0,1,2,3,4])
np.arange(1,10,2) 返回 array([1,3,5,7,9])
np.ones(shape,dtype=None,order='C')
a=np.ones(3) # 返回 array([1. 1. 1.])
b=np.ones((2,3))
b=np.ones((5,), dtype=np.int) # 返回 [1 1 1 1 1]
参数:
shape:整数或者整型元组定义返回数组的形状;可以是一个数(创建一维向量),也可以是一个元组(创建多维向量)
dtype : 数据类型,可选定义返回数组的类型。
order : {‘C’, ‘F’}, 可选规定返回数组元素在内存的存储顺序:C(C语言)-rowmajor;F(Fortran)column-major。
np.ones_like(a,dtype=float,order='C',subok=True)
返回:与a相同形状和数据类型的数组,并且数组中的值都为1
参数:
a:用a的形状和数据类型,来定义返回数组的属性
dtype : 数据类型,可选
order顺序 : {'C','F','A'或'K'},可选,覆盖结果的内存布局。
subok : bool,可选。True:使用a的内部数据类型,False:使用a数组的数据类型,默认为True

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

full创建指定值的数组与one类似只是能只能参数了例:
np.full(3,520) 返回 [520 520 520]
np.full((2,4),520)
使用random模块生成随机数组
import random
np.random.randn(d0,d1,…..,dn)
传1个数就是一维,2个数就是二维,n个数就是n维
例如:
a = np.random.randn() # 一个随机数
b = np.random.randn(3) # 3个数
c = np.random.randn(3,2) # 3行2列
d = np.random.randn(3,2,4) # 3块,每块是2行4列
需要四舍五入:
np.round(a,2) # 变量a,保留两位小数点
dtype给数据指定数据类型:

1
2
3
4
5
6
7
8
9
import numpy as np
a = np.array(range(1,8),dtype=float) # 修改数据类型
b = np.array(range(1,8),dtype='float32') # 修改数据类型和位数
print(a)
print(b)
print(a.dtype)
print(b.dtype)
print(type(a))
print(type(b))

多维数组

一维数组的定义:当数组中每个元素都只带有一个下标时,称这样的数组为一维数组,一维数组实质上是一组相同类型数据的线性集合。
二维数组的定义:二维数组本质上是以数组作为数组元素的数组,即数组的数组
reshape不改值修改形状
能变成2行5列,就能变回1行10个元素,想让他变成一维就给它传一个数,这个数必需是这个数组所有
值的全部个数。
a.reshape(1,10) 绝不等于 a.reshape(10) a.reshape(1,10)输出值为[[1,2,3,4,5,6,7,8,9,10]] 形状为(1,10)二维;而a.reshape(10)输出为[1,2,3,4,5,6,7,8,9,10]形状为(10,)一维
但是如果我不清楚这个数组中有多少个数,但是仍然想转成一维
a.flatten()
作用:将一个多维数组展开变成一个一维数组
注意区别:
shape:返回数组的维度
reshape:不改变数组的值,修改形状

1
2
3
4
5
6
import numpy as np
import random
a = np.arange(10).reshape(2,5) # 变成2行5列
b = a.reshape(10) # 变回1行1列
c = a.flatten() # 不清楚对方什么阵型,直接转一维
print(c)

数组计算

凡是形状一样的数组,假设数组a和数组b,可以直接用a+b 或 a-b
a+b 对应位置的数字进行计算(加减乘除)也就是一维和多维数组是可以计算的,只要它们在某一维度上是一样的形状,仍然是按位置计算。

1
2
3
4
5
6
import numpy as np
a = np.arange(6)
b = np.arange(24).reshape(4,6)
print(a)
print(b)
print(b-a)

结果为:

1
2
3
4
5
6
7
8
9
[0 1 2 3 4 5]
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[ 0 0 0 0 0 0]
[ 6 6 6 6 6 6]
[12 12 12 12 12 12]
[18 18 18 18 18 18]]

广播规则

广播的原则:
如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。
这句话乃是理解广播的核心。广播主要发生在两种情况,一种是两个数组的维数不相等,但是它们的后缘维度的轴长相符,另外一种是有一方的长度为1
上例中x的shape为(4,3),y的shape为(3,)。可以说x是二维的,而y是一维的。但是它们的后缘维度相等,x的第二维长度为3,和y的维度相同。x和y的shape并不一样,但是它们可以执行相加操作,这就是通过广播完成的。
从上面的图可以看到,(3,4,2)和(4,2)的维度是不相同的,前者为3维,后者为2维。但是它们后缘维度的轴长相同,都为(4,2)。同样,还有一些例
子:(4,2,3)和(2,3)是兼容的,(4,2,3)还和(3)是兼容的,后者需要在两个轴上面进行扩展。
这部分可以看pdf

基础索引与切片

1
2
3
4
import numpy
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(a[3],a[5],a[-1]) # 返回 3 5 9
print(a[2:4]) # 返回 array([2, 3])

语法:序列[开始位置下标:结束位置下标:步长]
步长是选取间隔,正负整数均可,默认为1;不包结束位置下标对应的数据,正负整数均可
A[0,0] # 取数组A的0行0列,返回值0
A[-1,2] # 取最后一行的第2列,返回值17
A[2] # 取第2行所有的列,返回array([10, 11, 12, 13, 14])
A[-1] # 取最后1行
A[0:-1] # 取除了最后1行之外其它所有行
A[0:2,2:4] #取0和1行,2和3列
A[:,2] # 取所有行中的第2列
三、切片修改(注意:会修改原来的数组)
由于Numpy经常处理大数组,避免每次都复制,所以切片修改时直接修改了数组
a[4:6] = 520 # 返回array([ 0, 1, 2, 3, 520, 520, 6, 7, 8, 9])
A[:1,:2]=520 # 修改0行1列的两个值

布尔索引

1
2
3
4
5
6
import numpy as np
数组 = np.arange(1,21).reshape(4,5)
print(数组)
筛选 = 数组>10
print(筛选) # 返回一个布尔数组,即有行又有列
print(数组[筛选]) # 返回所有为True的对应数字组成的数组,以一维数组展现

在,筛选 = 数组>10 中先把数组赋给筛选然后用比较运算符>大于 - 返回x是否大于y (a > b) 返回 False。

神奇索引

读取 = 数组[[1,5,7,2],[0,3,1,2]] # 取第1行第0列,第5行第3列,第7行第1列,第2行第2列
print(数组[:,[1,2]]) # 取所有行的,第1列和第2列
实例:获取数组中最大的前N个数字

1
2
3
4
5
6
7
8
9
10
import numpy as np
数组 = np.random.randint(1,100,10)
print(数组)
# 数组.argsort()会返回排序后的下标
# 取最大值对应的3个下标,因为默认升序,所以要用-3,从倒数第3个到最后一个
下标 = 数组.argsort()[-3:]
print(下标) # 返回的是最大3个数在数组中的下标
# 将下标传给数组
最大 = 数组[下标]
print(f'最大的三个数是{最大}')

代码中numpy.random.randint(low, high=None, size=None, dtype='l')
low: int
生成的数值最低要大于等于low。
(hign = None时,生成的数值要在[0, low)区间内)
high: int (可选)
如果使用这个值,则生成的数值在[low, high)区间。
size: int or tuple of ints(可选)
输出随机数的尺寸,比如size = n则输出总共n个随机数。默认是None的,仅仅返回满足要求的单一随机数。
dtype: dtype(可选):想要输出的格式。如int64、int等等

Numpy的轴

可以看到轴编号和shape元组的索引是对等的,所以这个编号可以理解为高维nd.array.shape产生的元组的索引
我们知道shape(4,3,2)表示数组的维度,既然shape的索引可以看做轴编号,那么一条轴其实就是一个维度
0轴对应的是最高维度3维,1轴对应2维,2轴对应的就是最低维度的1维
总结:凡是提到轴,先看数组的维度,有几维就有几个轴

沿轴切片

以下是二维数组,数组的维度是(3,3),这个元组的索引是 [0,1],表示这个2维数组有两条轴:0轴和1轴

1
2
3
4
import numpy as np
数组=np.array([ [1,2,3] , [4,5,6] , [7,8,9] ])
print(数组)
print(数组.shape)

print(数组[0:2])
这里有个很重要的概念, :2 是切片的第一个参数,约定俗成第一个参数就代表0轴 0轴表示2维,所以这个切片是在2维这个维度上切的,又叫“沿0轴切”。
这个2维数据是由3个1维数组组成的,这3个1维数组当然也有索引号也是[0,1,2],[ :2 ] 就表示它要切取2维(0轴)上3个1维数组中的索引 [ 0 ] 和索引
[ 1 ] ,于是得到 ([ 1, 2, 3 ]) 和 ([ 4, 5, 6 ]) 这两个1维数组。
print(数组[:2,1:])
就是在两个维度(轴)上各切一刀,第1个参数就是2维(0轴), :2 表示切取2维(0轴)上的索引 [ 0 ] 和索引 [ 1 ] ,即 ([ 1, 2, 3 ]) 和 ([ 4, 5, 6 ]) 这两个1维数组
第2个参数就是1维(1轴),1: 表示切取1维(1轴)上的索引 [ 1 ] 和索引 [ 2 ] ,即对数组 ([ 1, 2, 3 ]) 取 ([ 2,3 ]) ,对数组 ([ 4, 5, 6 ]) 取 ([ 5,6 ])
矩阵转置 transpose行列转置和swapaxes轴转置

随机数

seed 向随机数生成器传递随机状态种子:只要random.seed( * ) seed里面的值一样,那随机出来的结果就一样。所以说,seed的作用是让随机结果可重现。也就是说当我们设置相同的seed,每次生成的随机数相同。如果不设置seed,则每次会生成不同的随机数。使用同一个种子,每次生成的随机数序列都是相同的,也就是说重复运行程序生成的随机数仍然是相同的

1
2
3
4
5
import random
random.seed(10)
print(random.random()) # random.random()用来随机生成一个0到1之间的浮点数,包括零。
print(random.random())
print(random.random()) # 这里没有设置种子,随机数就不一样了

rand()返回[0,1]之间,从均匀分布中抽取样本

1
2
3
4
5
6
7
8
9
import numpy as np
一维 = np.random.rand(3)
print(一维)
print('-'*30)
二维 = np.random.rand(2,3)
print(二维)
print('-'*30)
三维 = np.random.rand(2,3,4)
print(三维)

我们数据分析的三部曲:Numpy、Pandas、matplotlib,后期我们在使用matplotlib画图时会用到均匀分布
Numpy linspace函数依照定义间隔生成均匀分布的数值。我们使用start和stop参数指定间隔,这里我们设定为0和100,同时指定在范围内生产5个观测值,因此函数生成5个均匀分布的元素。第一个是0,最后一个100,其他三个分布在0和100之间
绘制函数时,最后一个参数时隔取点绘制函数,影响函数的平滑

1
2
3
4
5
6
7
import numpy as np
import matplotlib.pyplot as plt
# 绘制正弦曲线
x轴 = np.linspace(-10,10,10) # 在[-10,10]闭区间或半闭区间中,数量为100
y轴 = np.sin(x轴) # sin正弦、cos余弦
plt.plot(x轴,y轴)
plt.show()

加入噪声np.random.rand(len(x轴))

1
2
3
4
5
6
7
import numpy as np
import matplotlib.pyplot as plt
# 绘制正弦曲线
x轴 = np.linspace(-10,10,100) # 在[-10,10]闭区间中,数量为100
y轴 = np.sin(x轴) + np.random.rand(len(x轴)) # 生成均匀分布,len(x轴)就是维度,相加就是定义元素的相加
plt.plot(x轴,y轴)
plt.show()

randn 返回标准正态分布随机数(浮点数)平均数0,方差1

1
2
3
4
5
6
7
8
9
10
import numpy as np
一维 = np.random.randn(3)
print(一维)
print('-'*30)
二维 = np.random.randn(2,3)
print(二维)
print('-'*30)
三维 = np.random.randn(2,3,4)
print(三维)
print('-'*30)

choice 从一维数组中生成随机数

1
2
3
4
5
6
7
8
import numpy as np
# 第一参数是一个1维数组,如果只有一个数字那就看成range(5)
# 第二参数是维度和元素个数,一个数字是1维,数字是几就是几个元素
a = np.random.choice(5,3)
print(f'从range(5)中拿随机数,生成只有3个元素的一维数组是:{a}')
shuffle(数组)把一个数进行随机排列
使用Numpy数组可以使你利用简单的数组表达式完成多种数据操作任务,而无须写大量的循环,这种利用数组表达式来替代循环的方法,称向量化。
通常,向量化的数组操作会比纯Python的等价实现在速度上快一到两个数量级(甚至更多)

数学和统计方法

方法 描述
sum 沿着轴向计算所有元素的累和,0长度的数组累和为0
average 加权平均,参数可以指定weights
prod 所有元素的乘积
mean 数学平均,0长度的数组平均值为NaN
std,var 标准差和方差,可以选择自由度调整(默认分母是n)
min,max 最小和最大值
argmin,argmax 最小和最大值的位置
cumsum 从0开始元素累积和
cumprod 从1开始元素累积积
median 中位数
prercentile 0-100百分位数
quantile 0-1分位数

一维数组

众数:出现次数最多的那个数
沿轴向进行计算,一维数组只有一个0轴
numpy.bincount函数是统计列表中元素出现的个数在机器学习中用到的很广泛,(机器学习和深度学习基本上以矩阵为主,尤其是K临近算法有时要添加权重改善分类或回归的精度)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np
a = np.array([1,2,3,4,3,5,3,6])
print(f'数组:{a}')
print(np.sum(a))
print(np.prod(a))
print(np.cumsum(a)) # 从0开始元素的累积和
print(np.cumprod(a)) # 从1开始元素的累积积
print(np.max(a))
print(np.min(a))
print(np.argmax(a)) # 最大值所在的下标
print(np.argmin(a)) # 最小值所在的下标
print(np.mean(a)) # 平均数
print(np.median(a)) # 中位数
print(np.average(a)) # 加权平均
counts = np.bincount(a) # 统计元素出现的个数,不能统计浮点数
print(np.argmax(counts)) # 返回众数,此方法不能用于二维数组

二维数组

关于numpy.cumsum()在官网中官方给了一个很好的例子。
在这里插入图片描述
cumsum的作用主要就是计算轴向的累加和。

里面最重要的参数就是axis

当里面的参数axis没有值时,默认是一个一维数组进行加和,即
a=np.array([[1,2,3],[4,5,6]])
np.cumsum()
输出1,3,6,10,15,21
即1,1+2,1+2+3,1+2+3+4,1+2+3+4+5,1+2+3+4+5+6

np.cumsum(axis=0),按行累加
输出
array([[1, 2, 3],
[5, 7, 9]], dtype=int32)
5=1+4,7=2+5,9=3+6

np.cumsum(axis=1),按列累加
输出
array([[ 1, 3, 6],
[ 4, 9, 15]], dtype=int32)
3=1+2,6=1+2+3
9=4+5,15=4+5+6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np
from scipy import stats
a = np.array([[1,3,6],[9,2,3],[2,3,3]])
print(f'数组:\n{a}')
print('-'*30)
print(np.sum(a))
print(np.prod(a))
print(np.cumsum(a)) # 从0开始元素的累积和,返回一维数组
print(np.cumprod(a)) # 从1开始元素的累积积,返回一维数组
print(np.max(a))
print(np.min(a))
print(np.argmax(a))
print(np.argmin(a))
print(np.mean(a))
print(np.median(a))
print(np.average(a))

数组的众数不建议在Numpy里面计算,在Pandas里面计算更简单。将一维数组转成Pandas的Series,然后调用mode()方法,有待研究

Numpy的axis参数的用途

axis=0代表行,axis=1代表列
所有的数学和统计函数都有这个参数,都可以使用我们想按行或按列使用时使用这个参数

1
2
3
4
5
6
7
import numpy as np
a = np.array([[1,3,6],[9,3,2],[1,4,3]])
print(f'数组:\n{a}')
print('-'*30)
print(np.sum(a,axis=0)) # 每行中的每个对应元素相加,返回一维数组
print('-'*30)
print(np.sum(a,axis=1)) # 每列中的每个元素相加,返回一维数组

其中思路正好是反的:axis=0 求每列的和。axis=1求每行的和。
数组对应到现实中的一种解释:

  1. 行:每行对应一个样本数据
  2. 列:每列代表样本的一个特征
    数据标准化:
    • 对于机器学习、神经网络来说,不同列的量纲是相同的,收敛更快。
    • 有两个特征,一个是商品单价1元至50元,另一个是销售数量3千个至1万个,这两个数字不可比,所以需要都做标准化。
    • 比如在Excel里,单价一个列,销售数量一个列,不同列代表不同特征,所以用axis=0做计算
    • 标准化一般使用:通过均值和方差实现
    数组 = (数组 - mean(数组,axis=0))/ std(数组, axis=0)

将条件逻辑作为数组操作

numpy.where调用方式为numpy.where(condition,1,2),满足条件的位置上返回结果赋值为1,不满足的位置上返回结果赋值为2

1
2
3
4
5
6
7
import numpy as np
a = np.array([[1,3,6],[9,3,2],[1,4,3]])
print(f'数组:\n{a}')
print('-'*30)
print(a>3)#TURE OR FALSE
print('-'*30)
print(np.where(a>3,520,1314))

布尔值数组方法

1
2
3
4
5
import numpy as np
a = np.array([[1,3,6],[9,3,2],[1,4,3]])
print(f'数组:\n{a}')
print('-'*30)
print((a>3).sum()) # 数组中大于3的数有多少个

对于布尔值数组,有两个常用方法any和all。
any:检查数组中是否至少有一个True
all:检查是否每个值都是True

1
2
3
4
import numpy as np
a = np.array([False,False,True,False])
print(a.any()) #TRUE
print(a.all()) #FALSE

按值大小排序 sort

ndarray.sort(axis=-1, kind='quicksort', order=None)
axis
排序沿数组的(轴)方向,0表示按行,1表示按列,N0表示展开来排序,默认值为-1,表示沿最后的轴排序
kind
排序的算法,提供了快排'quicksort'、混排'mergesort、堆排heapsort',默认为quicksort'
order
排序的字段名,可指定字段排序,默认为None
一维数组:

1
2
3
4
import numpy as np
a = np.array([3,6,7,9,2,1,8,5,4]) #默认升序
a.sort()
print(a)

二维数组:
二维数组按列排序就是按照1轴排序,对二维数组中的每一行一维数据而言默认升序

1
2
3
4
5
6
7
import numpy as np
a = np.array([[0,12,48],[4,18,14],[7,1,99]])
print(f'数组:\n{a}')
print('-'*30)
print(np.sort(a)) # 默认按最后的轴排序,就是(行,列)(0,1)
print('-'*30)
print(np.sort(a,axis=0)) # 按行排序

从大到小的索引 argsort

numpy.argsort(a, axis=-1, kind='quicksort', order=None)
对数组沿给定轴执行间接排序,并使用指定排序类型返回数据的索引数组。 这个索引数组用于构造排序后的数组。
参数类似于sort()
一维数组:

1
2
3
4
5
6
7
8
9
import numpy as np
x = np.array([59, 29, 39])
a = np.argsort(x)
print(f'索引升序:{a}') # 升序
# argsort函数返回的是数组值从小到大的索引值,[3, 1, 2]从小到大为[1,2,3],期对应的索引为[1,2,0]
print(f'数组升序:{x[a]}') # 以排序后的顺序重构原数组
b = np.argsort(-x) # 降序
print(f'索引降序:{b}')
print(f'数组升序:{x[b]}')

二维数组:
np.take的用法

1
2
3
4
5
6
7
import numpy as np
x = np.array([[0, 12, 48], [4, 18, 14], [7, 1, 99]])
a1 = np.argsort(x)
print(f'索引排序:\n{a1}')
print('-'*30)
# 以排序后的顺序重构原数组,注意与一维数组的形式不一样
print(np.array([np.take(x[i], x[i].argsort()) for i in range(3)]))

由于对列的索引排序所以take中的第一个参数不变

根据键值的字典序进行排序 lexsort

lexsort(keys, axis=-1)
lexsort()根据键值的字典序进行排序,支持对数组按指定行或列的顺序排序,间接排序,不修改原数组,返回索引。一般对一维数组使用argsort()。
默认按最后一行元素有小到大排序, 返回最后一行元素排序后索引所在位置。

唯一值与其它集合逻辑 unique和in1d

去重复:
unique(x) 计算x的唯一值,并排序

1
2
3
4
5
import numpy as np
姓名 = np.array(['孙悟空','猪八戒','孙悟空','沙和尚','孙悟空','唐僧'])
print(np.unique(姓名))
数组 = np.array([1,3,1,3,5,3,1,3,7,3,5,6])
print(np.unique(数组))

检查一个数组中的值是否在另外一个数组中,并返回一个布尔数组:
in1d(x,y) 计算x中的元素是否包含在y中,返回一个布尔值数组

1
2
3
import numpy as np
a = np.array([6,0,0,3,2,5,6])
print(np.in1d(a,[2,3,6]))

浅拷贝与深拷贝

浅拷贝
a=b 不能这样赋值,因为a和b相互影响,在内存里a变了b也会发生变化
a=b[:] 视图操作,一种切片,会创建新的对象a,但是a的数据完全由b保管,他们两个的数据变化是一致的
深拷贝
a=b.copy() 复制,a和b互不影响,相当于是重新开辟了一个空间保存b的值,然后让a指向b.copy()

Pandas

RT

数据类型与新建文件

数据类型 说明 新建方法
csv、tsv、txt 用逗号分隔、tab分割的纯文本文件 pd.to_csv
excel xls或xlsx pd.to_excel
mysql 关系数据库表 pd.to_sq
一、新建空白Excel文件:
报错:ModuleNotFoundError: No module named 'openpyxl'使用pip list发现没有openpyxl包安装后无错误

1
2
3
4
5
import pandas as pd 
路径 = 'D:\python-learn\新建空白文件.xlsx'
数据=pd.DataFrame( )
数据.to_excel(路径)
print('新建空白文件.xlsx成功')

注意xlsx文件打开后不可写Permission denied: 'd:/python-learn/新建空白文件.xlsx'
二、新建文件同时写入数据:

1
2
3
4
5
import pandas as pd
路径 = 'D:\python-learn\新建空白文件.xlsx'
数据=pd.DataFrame({'id':[1,2,3],'姓名':['叶问','李小龙','孙兴华']})
数据.to_excel(路径)
print('新建空白文件.xlsx成功')

三、将id设置为索引

1
2
3
4
5
6
import pandas as pd
路径 = 'D:\python-learn\新建空白文件.xlsx'
数据=pd.DataFrame({'id':[1,2,3],'姓名':['叶问','李小龙','孙兴华']}) # 写入的数据
数据=数据.set_index('id') # 将id设置为索引
数据.to_excel(路径) # 将数据写入Excel文件
print(数据)

读取数据

数据类型 说明 读取方法
csv、tsv、txt 默认英文逗号分隔 pd.read_csv
csv、tsv、txt 默认\t分隔 pd.read_table
excel xls或xlsx pd.read_excel
mysql 关系数据库表 pd.read_sql
体验两种方法的区别,与sep指定分隔符切记:如果分隔符不止一种,使用正则表达式sep='\s+',一般使用CSV文件存储大数据,匹配空白字符(包括空格、换行符、制表符等),也就是说既有空白字符又有\t分隔符可以用pd.read_table(路径,sep='\s+')

1
2
3
4
import pandas as pd 
路径 = 'D:\python-learn\读取数据.txt'
读取数据 = pd.read_csv(路径)
print(读取数据)

二、查看前几行数据
print(读取数据.head()) # 默认是5行,指定行数写小括号里
三、查看数据的形状,返回(行数、列数)
print(读取数据.shape)
四、 查看列名列表
print(读取数据.columns)
五、查看索引列
print(读取数据.index)
六、查看每一列数据类型
print(读取数据.dtypes)

自己制定分隔符、列名,自定义表头

读取数据 = pd.read_csv(路径,sep=',',header=None,names=['姓名','年龄','地址','电话','入职日期'],encoding='utf-8',index_col='入职日期')
sep参数:英文逗号或"\t",从文件、url、文件型对象中加载带分隔符的数据,默认为'\t'。(read_csv默认分隔符是逗号),可以通过制定sep 参数来修改默认分隔符
header参数:读取没有标题的文件时,默认为第一行作为列标题,设置header=None,意思就是没有表头,后面你自己写表头
names参数:通过names=['a','b','c']可以自己设置列标题。
参数 描述
sep 分隔符或正则表达式 sep='\s+' 注意如果数据中既有英文也有中文逗号可以sep=','
header 列名的行号,默认0(第一行),如果没有列名应该为None
names 列名,与header=None一起使用,自定义表头名称
index_col 索引的列号或列名,可以是一个单一的名称或数字,也可以是一个分层索引
skiprows 从文件开始处,需要跳过的行数或行号列表
encoding 文本编码,例如utf-8
nrows 从文件开头处读入的行数 nrows=3

txt文件转csv文件

1
2
3
4
import pandas as pd
数据 = pd.read_csv('D:\python-learn\读取数据.txt')
数据.to_csv('D:\python-learn\读取数据.csv')
print(数据)

读取MySQL数据库

补充SQL in Python 之 PyMysql

1
2
3
4
5
import pandas as pd
import pymysql
连接对象 = pymysql.connect(host = 'localhost',user = 'root',password = '1234',database = 'test',charset = 'utf8')
读取文件 = pd.read_sql("select * from 1班",con=连接对象)#第1个参数是SQL查询语句,第2参数是数据库连接
print(读取文件)

读取Excel文件

读取Excel并添加自定义表头

1
2
3
4
import pandas as pd
路径 = 'D:\python-learn\工作簿.xlsx'
读取数据=pd.read_excel(路径,header=None,names=['序号','姓名','年龄','手机','地址','入职日期'])
print(读取数据)

to_excel可用于写入文件xxx.to_excel(excel1.xlsx, sheet_name='Sheet1', index=False)注意第一个参数别加引号,参数设置的不好会破坏原来的文件 # index false为不写入索引,关闭文档再调用否则没权限;index_col='序号'可用于添加序号

1
2
3
4
5
6
7
8
import pandas as pd
路径 = 'D:\python-learn\工作簿.xlsx'
读取数据 = pd.read_excel(路径,header=0,index_col='序号')
读取数据.columns=['序号','姓名','年龄','地址','电话','入职日期'] # 给每个列重复设置表头
读取数据=读取数据.set_index('序号',inplace=True) # 只在index上面改,不要生成新的
print(读取数据.columns) # 查看列名列表,index和columns是分开的
print(读取数据)
读取数据.to_excel('路径') # 写入到Excel文件

二、查看前几行数据
print(读取数据.head()) # 默认是5行,指定行数写小括号里
三、查看数据的形状,返回(行数、列数)
print(读取数据.shape)
四、 查看列名列表
print(读取数据.columns)
五、查看索引列
print(读取数据.index)
六、查看每一列数据类型
print(读取数据.dtypes)
七、自己设置并写入表头【第一种方法】
import pandas as pd
路径 = 'c:/pandas/读取文件.xlsx'
读取数据 = pd.read_excel(路径,header=None)
读取数据.columns=['序号','姓名','年龄','地址','电话','入职日期'] # 给每个列重复设置表头
读取数据=读取数据.set_index('序号') # 重新指定索引列
print(读取数据.columns) # 查看列名列表
读取数据.to_excel('路径') # 写入到Excel文件
八、自己设置并写入表头【第二种方法】
import pandas as pd
路径 = 'c:/pandas/读取文件.xlsx'
读取数据 = pd.read_excel(路径,header=None,index_col='序号')
读取数据.columns=['序号','姓名','年龄','地址','电话','入职日期'] # 给每个列重复设置表头
读取数据=读取数据.set_index('序号',inplace=True) # 只在index上面改,不要生成新的
print(读取数据.columns) # 查看列名列表,index和columns是分开的
读取数据.to_excel('路径') # 写入到Excel文件
孙兴华推荐方法:
import pandas as pd
路径 = 'c:/pandas/读取文件.xlsx'
读取数据 = pd.read_excel(路径,header=None,names=['序号','姓名','年龄','手机','地址','入职日期'], index_col='序号')
默认第0行为标题行
如果自己设置表头,这里要设置无表头
指定哪列是index
2.3 读取Excel文件
2020年4月2日 23:13
分区 基础 的第 10 页
读取数据 = pd.read_excel(路径,header=None,names=['序号','姓名','年龄','手机','地址','入职日期'], index_col='序号')
print(读取数据)
读取数据.to_excel(路径)

pandas数据结构

DataFrame:二维数据,整个表格,多行多列简称df
df.index:索引列
df.columns:列名
Series:一维数据,一行或一列
Series是一种类似于一维数组的对象,它由一组数据(不同数据类型)以及一组与之相关的数据标签(即索引)组成。

仅有数据列表即可产生最简单的Series

1
2
3
4
5
import pandas as pd
数据= pd.Series([520,'孙兴华',1314,'2020-07-30']) # 左侧是索引,右侧是数据
print(数据)
print(数据.index) # 获取索引,返回索引的(起始值,结束值,步长)RangeIndex(start=0, stop=4, step=1)
print(数据.values) # 获取数据,返回值序列,打印元素值的列表 [520 '孙兴华' 1314 '2020-07-30']

我们指定Series的索引

1
2
3
4
import pandas as pd
数据= pd.Series([520,'孙兴华',1314,'2020-07-30'],index=['a','b','c','d']) # 指定索引
print(数据)
print(数据.index) # 返回指定的索引 Index(['a', 'b', 'c', 'd'], dtype='object')

使用Python字典创建Series

1
2
3
4
5
import pandas as pd
字典={'姓名':'孙兴华','性别':'男','年龄':'20','地址':'花果山水帘洞'}
数据=pd.Series(字典)
print(数据)
print(数据.index) # 返回key Index(['姓名', '性别', '年龄', '地址'], dtype='object')

print(数据) # 查询整个字典
print(数据['姓名']) # 通过key可以查对应的值
type(数据['年龄']) # 通过key可以查对应值的类型
print(数据[['姓名','年龄']]) # 通过多个key查对应的值 #姓名 孙兴华
年龄 20
type(数据[['姓名','年龄']]) # 注意:他不返回值的类型,而返回Series

键和值存在两个列表中,创建Series

1
2
3
4
5
import pandas as pd
列表1 = ['姓名','性别','年龄']
列表2 = ['孙兴华','男',20]
数据 = pd.Series(列表2,index=列表1) # 指定谁是索引
print(数据)

Series只是一个序列,可能是一行,也可能是一列,现在无法确定用行的方法,把Series加入DataFrame,就是行,反之就是列。
常用方法
数据.index #查看索引
数据.values #查看数值
数据.isnull() #查看为空的,返回布尔型
数据.notnull()
数据.sort_index() #按索引排序
数据.sort_values() #按数值排序

认识DataFrame

• 每列可以是不同的值类型(数值、字符串、布尔值等)
• 既有行索引index,也有列索引columns
• 可以被看做由Series组成的字典
DataFrame是一个表格型的数据结构
创建DataFrame最常用的方法,参考读取CSV、TXT、Excel、MySQL等
创建二维数组,列索引为a,b,c:

1
2
3
4
5
6
7
import pandas as pd
数据=pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]],columns=['a','b','c'])
print(数据)
print(数据['a'][0] ) #a列0行
print(数据.loc[0]['a'] ) #0行a列
print(数据.iloc[0][0] ) #0行0列的位置
print(数据[['a','b']]) #a,b列上的数据

loc就根据这个index来索引对应的行。iloc并不是根据index来索引,而是根据行号来索引,行号从0开始,逐次加1。
a. 数据.loc方法:根据行,列的标签值查询
b. 数据.iloc方法:根据行,列的数字位置查询

DataFrame 整个表格

DataFrame是一个表格型的数据结构:
每列可以是不同的值类型(数值、字符串、布尔值等)
既有行索引index,也有列索引columns
可以被看做由Series组成的字典
创建DataFrame最常用的方法,参考读取CSV、TXT、Excel、MySQL等
多个字典序列创建DataFrame:

1
2
3
4
5
6
7
8
9
10
11
import pandas as pd
字典 = {
'姓名':['孙兴华','李小龙','叶问'],
'年龄':[20,80,127],
'功夫':['撸铁','截拳道','咏春']
}
数据 = pd.DataFrame(字典)
print(数据)
print(数据.dtypes) # 返回每一列的类型
print(数据.columns) # 返回列索引,以列表形式返回:[列名1,列名2,…]
print(数据.index) # 返回行索引,(起始,结束,步长)

从DataFrame中查询出Series
print(数据['姓名']) # 返回索引和这一列数据
• 如果只查询一行,返回的是pd.Series
type(数据['姓名']) # 类型返回Series
print(数据.loc[1]) # 这时,它的索引是列名
• 如果查询多列,返回的是pd.DataFrame
type(df.loc[1]) # 类型返回Series
print(数据[['姓名','年龄']]) # 返回索引和这两列数据
• 如果查询多行,返回的是pd.DataFrame
type(数据[['姓名','年龄']]) # 类型返回DataFrame
print(数据.loc[1:3]) # 返回前3行,包括结束值
type(数据.loc[1:3]) # 类型返回DataFrame
将多个Series加入DataFrame: index=[1,2,3]意思是索引名为1,2,3且3个数据的index他有对齐的功能,例如把数据3的index改成2,3,4,没有值的地方会显示nan

1
2
3
4
5
6
import pandas as pd
数据1 = pd.Series(['叶问','李小龙','孙兴华'],index=[1,2,3],name='姓名')
数据2 = pd.Series(['男','男','男'],index=[1,2,3],name='性别')
数据3 = pd.Series([127,80,20],index=[1,2,3],name='年龄')
1 = pd.DataFrame({数据1.name:数据1,数据2.name:数据2,数据3.name:数据3})
print(表1)

DataFrame常用方法

常用方法
数据.head( 5 ) #查看前5行
数据.tail( 3 ) #查看后3行
数据.values #查看数值
数据shape #查看行数、列数
数据.fillna(0) #将空值填充0
数据.replace( 1, -1) #将1替换成-1
数据.isnull() #查找数据中出现的空值
数据.notnull() #非空值
数据.dropna() #删除空值
数据.unique() #查看唯一值
数据.reset_index() #修改、删除,原有索引,详见例1
数据.columns #查看数据的列名
数据.index #查看索引
数据.sort_index() #索引排序
数据.sort_values() #值排序
pd.merge(数据1,数据1) #合并
pd.concat([数据1,数据2]) #合并,与merge的区别,自查
pd.pivot_table( 数据 ) #用df做数据透视表(类似于Excel的数透)

1
2
3
4
5
import pandas as pd
路径 = 'd:/python-learn/分组2.xlsx'
读取数据 = pd.read_excel(路径,header=None)
print(读取数据.reset_index(drop=True)) # 索引被直接删除
print(读取数据.reset_index(drop=False)) # 索引列会被还原为普通列

连接查询[数据合并与重塑]

首先merge的操作非常类似sql里面的join,实现将两个Dataframe根据一些共有的列连接起来,当然,在实际场景中,这些共有列一般是Id,连接方式也丰富多样,可以选择inner(默认),left,right,outer 这几种模式,分别对应的是内连接,左连接,右连接,全外连接

1
2
3
4
5
6
7
8
9
10
import pandas as pd
import numpy as np
数据1=pd.DataFrame({'姓名':['叶问','李小龙','孙兴华','李小龙','叶问','叶问'],'出手次数1':np.arange(6)})
数据2=pd.DataFrame({'姓名':['黄飞鸿','孙兴华','李小龙'],'出手次数2':[1,2,3]})
print(数据1)
print(30*'*')
print(数据2)
数据三=pd.merge(数据1,数据2)
print(30*'*')
print(数据三)

数据三=pd.merge(数据1,数据2)相当于数据3 = pd.merge(数据1,数据2,on='姓名',how='inner')
左连接:第一列为基准
数据3 = pd.merge(数据1,数据2,on='姓名',how='left')
OuterMerge (全连接):
数据3 = pd.merge(数据1,数据2,on='姓名',how='outer')全部数据取并集
MultipleKey Merge (基于多个key上的merge):
刚才我们都是仅仅实现的在一个key上的merge,当然我们也可以实现基于多个keys的merge改变On=的参数可使得二维键值合并

1
2
3
4
5
6
7
8
9
import pandas as pd
数据1 = pd.DataFrame({'姓名': ['张三', '张三', '王五'],'班级': ['1班', '2班', '1班'],'分数': [10,20,30]})
print(数据1)
数据2 = pd.DataFrame({'姓名': ['张三', '张三', '王五','王五'],'班级': ['1班', '1班', '1班','2班'],'分数': [40,50,60,70]})
print(数据2)
数据3= pd.merge(数据1,数据2,on=['姓名','班级']) # 内连接(交集)的结果
print(数据3)
数据4= pd.merge(数据1,数据2,on=['姓名','班级'],how='outer') # 外连接(并集)的结果
print(数据4)

Merge on Index (基于index上的merge) :
我们还可以实现几个Dataframe基于Index的merge,还是老样子,先让我们创建两个Dataframe

1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd
数据1 = pd.DataFrame({'姓名': ['张三','李四','王五','张三','李四'],'次数':range(5)})
数据2 = pd.DataFrame({'数据': [10, 20]}, index=['张三','李四'])
数据3=pd.merge(数据1,数据2,left_on='姓名',right_index=True)
print(数据1)
print(30*'*')
print(数据2)
print(30*'*')
print(数据3)
print(30*'*')
数据4=pd.merge(数据1,数据2,left_on='姓名',right_index=True,how='outer')
print(数据4)

总结
(1)通过on指定数据合并对齐的列 (2)没有指定how的话默认使用inner方法,除了内连接,还包括左连接、右连接、全外连接

分组聚合

在pandas中,实现分组操作的代码很简单,仅需一行代码,在这里,将上面的数据集按照company字段进行划分:group = data.groupby("company")
for groupy分组:

1
2
3
4
5
6
7
import pandas as pd
路径='d:/python-learn/分组.xlsx'
数据=pd.read_excel(路径)
for (i,j),group in 数据.groupby(['城市','区']):
print(i) #所有城市的分组遍历
print(j) #所有区的分组遍历
print(group) #分组

分组聚合:数据2=数据.groupby(['城市','区'])[['人数']].sum()按城市和区分组,再用人数聚合
to_excel(DIY路径)可以把分组聚合后的文件另存为!!!不要使用原路径防止误操作覆盖原来好的文件

1
2
3
4
5
6
import pandas as pd
路径='d:/python-learn/分组.xlsx'
数据=pd.read_excel(路径)
数据2=数据.groupby(['城市','区'])[['人数']].sum()
print(数据2)
数据2.to_excel('d:/python-learn/分组聚合.xlsx')

结果为

1
2
3
4
5
6
          人数
城市 区
北京市 东城区 88
西城区 112
天津 南开区 108
和平区 97

也可以将多个属性聚类,比如数据2=数据.groupby(['城市','区'])[['人数','金额']].sum()
对各列分别进行函数运算:

1
2
3
4
5
6
7
import pandas as pd
路径 = 'd:/python-learn/分组2.xlsx'
数据 = pd.read_excel(路径)
#不同列的不同计算方法
字典 = {'1月':'count','2月':sum,'3月':max,'4月':'mean'}
数据2 = 数据.groupby('店名').agg(字典)
print(数据2)

注意:
如果按一列聚合,只传列名字符串,如果多个就要传由列名组成的列表
聚合方法可以使用 Pandas 的数学统计函数 或者 Numpy 的统计函数
如果是 python 的内置统计函数,直接使用变量,不需要加引号
agg函数一般与groupby配合使用,agg是基于列的聚合操作,而groupby是基于行的
DataFrame.agg(func,axis = 0,* args,** kwargs )
func : 函数,函数名称,函数列表,字典{‘行名/列名’,‘函数名’}
使用指定轴上的一个或多个操作进行聚合。

1
2
3
4
5
6
7
import pandas as pd
路径 = 'd:/python-learn/分组2.xlsx'
数据 = pd.read_excel(路径,index_col='店名')
#不同列的不同计算方法
字典 = {'1月':'一季度','2月':'一季度','3月':'一季度','4月':'二季度'}
数据2 = 数据.groupby(字典,axis=1).sum()
print(数据2)

在read_excel中添加索引,先设计字典在按列axis=1按照字典值求和sum()
默认是对索引聚类,例如对店名的长度聚类

1
2
3
4
5
import pandas as pd
路径 = 'd:/python-learn/分组2.xlsx'
数据 = pd.read_excel(路径,index_col='店名')
数据2 = 数据.groupby(len).sum()
print(数据2)

对索引的名称长度和所在城市聚合
S1=['北京','北京','北京','北京','天津天津'] 数据2=数据.groupby([len.S1]).sum()
统计数值类型数据先对文字设置索引
groupby详细用法:
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)
by:接收映射、函数、标签或标签列表;用于确定聚合的组。
axis:接收0/1;用于表示沿行(0)或列(1)分割。
level:接收int、级别名称或序列,默认为None;如果轴是一个多索引(层次化),则按一个或多个特定级别分组。
as_index:接收布尔值,默认Ture;Ture则返回以组标签为索引的对象,False则不以组标签为索引。
mean()函数功能:求取均值。

1
2
3
4
5
import pandas as pd
路径 = 'd:/python-learn/分组3.xlsx'
数据 = pd.read_excel(路径,index_col=[0,1]) #按男,女索引
数据2=数据.groupby(level='班级').mean()
print(数据2)