高效Python之Numpy

Numpy是Python中非常重要的三方库,这篇文章主要记录一下几个问题:

  1. Python中是有list结构的,为什么Numpy还存在这样一个第三方的
    核心数组结构?
  2. Numpy灵魂对象 ndarray(N-dimensional array object)、ufunc(universal
    function object)

一、 Numpy中的数组结构

Python自身的列表list的元素在系统内存中是分散存储 的,而NumPy数组存储在一个均匀连续的内存块中。这样数组计算遍历所有的元素,不用像列表list还需要对内存地址进行查找,从而节省了计算资源。

在内存访问模式中,缓存会直接把字节块从RAM加载到CPU寄存器中。因为数据连续的存储在内存中, NumPy直接利用现代CPU的矢量化指令计算,加载寄
存器中的多个连续浮点数。另外NumPy中的矩阵计算可以采用多线程的方式,充分利用多核CPU计算资源,大大提升了计算效率。

另外,在进行算法时应 避免采用隐式拷贝

a=1+b
b+=1      推荐写法
同理 b*=1   ...

二、 ndarray、ufunc介绍

1. ndarray

  1. 数组
    ndarray实际上是多维数组的含义。在NumPy数组中,维数称为(rank),一维数组的秩为1,二维数组的秩为2,以此类推。在NumPy中,每一个线性的数组称
    为一个(axes),其实秩就是描述轴的数量。
import  numpy as np
a=np.array([1,2,3])
b=np.array([[1,2,3],[7,8,0]])
b[1,0]=100

print(a.shape)        #获取数组的大小
print(b.shape)
print(b)
print(a.dtype)        #获取元素的类型

//////////结果分割线////////
(3,)
(2, 3)
[[  1   2   3]
 [100   8   0]]
  1. 结构化数组
    对象的定义在ndarray中怎么表示呢?
    numpy的做法相当于先定义一个schema,创建数组的时候会按照schema去"匹配"schema的类型和名称.
    eg:
import  numpy as np
persontype=np.dtype([("name","U20"),("age","i")])
personInfos=np.array([("曹操",28),("刘备",28)],persontype)
print(personInfos)                          //打印数组
print(personInfos["name"])        //获取所有的name属性
print(personInfos[0])                  //第一个
print(personInfos[0]["name"])

//////////结果分割线////////
[('曹操', 28) ('刘备', 28)]
['曹操' '刘备']
('曹操', 28)
曹操
字符代码 对应类型
b 布尔型
i 有符号整型,'i1', 'i2', 'i4', 'i8' 对应 int8, int16, int32, int64
u 无符号整型,'u1', 'u2', 'u4', 'u8' 对应 uint8, uint16, uint32, uint64
f 浮点型,'f2', 'f4', 'f8' 对应 float16, float32, float64
c 复数,'c8', 'c16' 对应 complex64, complex128
m timedelta64(时间间隔),本质上是个 int64
M(大写) datetime64(日期时间)
O(大写) Python 对象
S(大写)/ a (byte-)字符串,只能包含 ASCII 码字符,S 或 a 后带数字表示字符串长度,超出部分将被截断,例如 S20、a10
U(大写) Unicode 字符串,U 后带数字表示字符串长度,超出部分将被截断,例如 U20
V(大写) bytes 数组,V 后带数字表示数组长度,超出部分将被截断,不足则补零

2. ufunc

ufunc(universal function),
1. 数组的创建(arange()、linspace())

更多方式参考: https://numpy.org/doc/1.17/user/basics.creation.html

arange()会创建指定步长的数组,并在指定的开始值和结束值之间等距间隔
linspace()会创建具有指定数量元素的数组,并在指定的开始值和结束值之间等距间隔

import numpy as np
x1 = np.arange(1,11,2)
x2 = np.linspace(1,9,5,dtype=int)     #默认为float
print(x1)
print(x2)

//////////结果分割线////////
[1 3 5 7 9]
[1 3 5 7 9]        不指定dtype则结果为  [1. 3. 5. 7. 9.]

2. 算数运算
通过NumPy可以自由地创建等差数组,同时也可以进行加、减、乘、除、求n次方和取余数

axis参数的含义,axis=0,代表压缩行,axis=1,代表压缩列;
eg: [[1,2,3],[4,5,6]]求平均值,axi=0,代表压缩矩阵的行,对每一列求平均值变成一行n列的矩阵。
同理axi=1,压缩列,对每一行【操作】后变成n行一列的矩阵

import numpy as np
x1 = np.arange(1,11,2)        #从1开始,每隔2生成一个元素,[1,3,5,7,9]
x2 = np.linspace(1,9,5)       #1-9平分成5等分(包括结束值) , [1,3,5,7,9]
print(x1)
print(x2)

#计算单个数组平均值
print(np.mean(x1))

x3=np.array([[1,2,3],[5,6,9]])
print(np.mean(x3))                           #默认计算所有元素的平均值,(1+2+3+5+6+9)/6
print(np.mean(x3,axis=0))                    #axis=0,代表压缩行,即计算结果[(1+5)/2,(2+6)/2,(3+9)/2];axis=1,代表压缩列,计算结果[(1+2+3)/3,(5+6+9)/3]
print(np.mean(x3,axis=1))

#数组之间加法
print("x1,x2 add value: ",np.add(x1,x2))                            #加法
print("x1,x2 subtract value: ",np.subtract(x1, x2))          #减法
print("x1,x2 multiply value: ",np.multiply(x1, x2))          #乘法
print("x1,x2 divide value: ",np.divide(x1, x2))                #除法
print("x1,x2 power value: ",np.power(x1, x2))                #以x1中每个元素为基数,x2元素为幂次,求n次方
print("x1,x2 remainder value: ",np.remainder(x1, x2))      #  equal    np.mod(x1,x2)  求余

3. 统计函数
Numpy中提供了最大值、最小值、平均值,是否符合正态分布,方差、标准差等等对数据的统计函数。
(示例在文末)

  • 最大最小 amax()、amin()
  • 最大最小差值 ptp()
  • 前第百分之几的数值 percentile() ,可以实现最小值,最大值,中位数求值(q=0,100,50)
  • 中位数median()、平均数mean()
  • 加权平均值average(),通过指定weights参数设置权重数组,默认是数值中所有数字权重一样
  • 方差var()、标准差std()

4. 排序
可以使用sort函数, sort(a, axis=-1, kind=‘quicksort’, order=None),默认情况下
使用的是快速排序;在kind里,可以指定quicksort、 mergesort、 heapsort分别表示快速排序、合并排序、堆排序。同样axis默认是-1,即沿着数组的最后一个轴进行
排序,也可以取不同的axis轴,或者axis=None代表采用扁平化(即所有元素平铺)的方式作为一个向量进行排序。另外order字段,对于结构化的数组可以指定按照某个字段进行排序


import numpy as np
x1 = np.arange(1,11,2)        #从1开始,每隔2生成一个元素,[1,3,5,7,9]
x2 = np.linspace(1,9,5)       #1-9平分成5等分(包括结束值) , [1,3,5,7,9]
print(x1)
print(x2)

#计算单个数组平均值
print(np.mean(x1))

x3=np.array([[1,2,3],[5,6,9]])
print(np.mean(x3))                           #默认计算所有元素的平均值,(1+2+3+5+6+9)/6
print(np.mean(x3,axis=0))                    #axis=0,代表压缩行,即计算结果[(1+5)/2,(2+6)/2,(3+9)/2];axis=1,代表压缩列,计算结果[(1+2+3)/3,(5+6+9)/3]
print(np.mean(x3,axis=1))

#数组之间加法
print("x1,x2 add value: ",np.add(x1,x2))
print("x1,x2 subtract value: ",np.subtract(x1, x2))
print("x1,x2 multiply value: ",np.multiply(x1, x2))
print("x1,x2 divide value: ",np.divide(x1, x2))
print("x1,x2 power value: ",np.power(x1, x2))
print("x1,x2 remainder value: ",np.remainder(x1, x2))      #  equal    np.mod(x1,x2)

x4=np.array([[1,8,3],[4,5,6]])
print("array x4 min value: ",np.amin(x4))
print("array x4 min value: ",np.amin(x4,axis=0))
print("array x4 max value: ",np.amax(x4))

x5=np.array([[1,8,3],[4,5,6],[20,10,50]])   
print("array x4 max and min subtract: ",np.ptp(x5))       #统计最大值与最小值之差  ,50-1  
print("one axis max and min subtract: ",np.ptp(x5,0))     #压缩行axis可以省略 -> [1,4,10],[8,5,20],[3,6,50] ->[10-1,20-5,50-3]

print("x4 mid num: ",np.percentile(x4,50))                 #  percentile求(从小到大)前第百分之几的数值,[1,3,4,5,6,8],50%就是求中位数(总数量为偶数就是两个中间相加除以2),即等于(4+5)/2
print("x5 mid num: ",np.percentile(x5,50))                 # [1,3,4,5,6,8,10,20,50]  即6
print("x4 one axis mid num: ",np.percentile(x4,50,axis=0))          #axis同理 ,压缩行求中位数
print("x4 max num Via percentile: ",np.percentile(x4,100))          #q=100,代表最大值
print("x4 min num Via percentile: ",np.percentile(x4,0))            #q=0,最小值

print("x4 min num: ",np.median(x4))                                 # 中位数
print("x5 min num: ",np.median(x5))

print("x4 average: ",np.average(x4))                                #加权平均值,默认是所有数字权重一样
print("x4 average: ",np.average(x4,weights=[[2,3,2],[8,1,2]]))      #(2*1+3*8+2*3+8*4+1*5+2*6)/(2+3+2+8+1+2)=4.5

print("x4 方差: ",np.var(x4))
print("x4 标准差: ",np.std(x4))

print("sort x4: ",np.sort(x5,axis=1))           #0表示对列排序,1表示对行排序
print("sort x4: ",np.sort(x5,axis=None))           # [ 1  3  4  5  6  8 10 20 50] 
# 练习题:统计全班的成绩
# 假设一个团队里有5名学员,成绩如下表所示。你可以用NumPy统计下这些人在语文、英语、数学中的平均成绩、最小成绩、最大成绩、方差、标准差。然后把这
# 些人的总成绩排序,得出名次进行成绩输出。
import numpy as np
from operator import attrgetter,itemgetter
schema=np.dtype([("name","U20"),("languageScore","i"),("mathScore","i"),("englishScore","i")])
scoreList=np.array([("张飞",60,30,65),("关羽",95,98,85),("赵云",93,96,92),("黄忠",90,77,88),("典韦",80,90,90)],dtype=schema)
print("语文平均成绩: ",np.mean(scoreList[:]["languageScore"]))
print("语文最低分: ",np.amin(scoreList[:]["languageScore"]))
print("语文高分: ",np.amax(scoreList[:]["languageScore"]))
print("语文方差: ",np.var(scoreList[:]["languageScore"]))
print("语文标准差: ",np.std(scoreList[:]["languageScore"]))
print("------------------------------------------")
print("数学平均成绩: ",np.mean(scoreList[:]["mathScore"]))
print("数学最低分: ",np.amin(scoreList[:]["mathScore"]))
print("数学最高分: ",np.amax(scoreList[:]["mathScore"]))
print("数学方差: ",np.var(scoreList[:]["mathScore"]))
print("数学标准差: ",np.std(scoreList[:]["mathScore"]))
print("------------------------------------------")
print("英语平均成绩: ",np.mean(scoreList[:]["englishScore"]))
print("英语最低分: ",np.amin(scoreList[:]["englishScore"]))
print("英语最高分: ",np.amax(scoreList[:]["englishScore"]))
print("英语方差: ",np.var(scoreList[:]["englishScore"]))
print("英语标准差: ",np.std(scoreList[:]["englishScore"]))
print("------------------------------------------")

#默认升序,指定True为逆序
print(sorted(scoreList,key=lambda x:x[1]+x[2]+x[3],reverse=True))

你可能感兴趣的:(高效Python之Numpy)