当前位置: 首页 > news >正文

NumPy的常用函数

1. 常量

常量含义
np.pi圆周率
np.e自然常数
np.euler_gamma欧拉常数
np.nan非数字
np.inf无穷大

两个np.nan不相等,但两个np.inf是相等的,判断一个数组元素是否是np.nannp.inf,需要使用np.isnan()np.isinf()这两个相应的函数,而不是使用两个等号的逻辑表达式

import numpy as np

a = np.array([1, 2 ,np.nan, np.inf])
print(a.dtype)
a[0] = np.nan
a[1] = np.inf
print(a)
# 两个np.nan不相等
print(a[0] == a[2])
# 两个np.inf
print(a[1] == a[3])
# 判断一个数组元素是否是np.nan
print(np.isnan(a[0]))
# 判断一个数组元素是否是np.inf
print(np.isinf(a[1]))
import numpy as np

a = np.array([9, 3, np.nan, 5, 3])
a = np.repeat(a, 2)[:-1]
a[1::2] += (a[2::2]-a[1::2])/2
print(a)

2. 命名空间

对于NumPy函数的使用,可能会有这样的困惑:实现同样的功能,一个函数却有两种写法;有时以为某个函数可以有两种写法,但用起来却会出错,归纳起来,这些困惑有以下三种类型

  • 都是求和、求极值,下面两种写法有什么区别么?

    import numpy as np
    
    a = np.random.random(10)
    print(a.max(), np.max(a))
    print(a.sum(), np.sum(a))
    
  • 同样是赋值,为什么深复制copy()两种写法都行,而浅复制view()则只有数组的方法?

    import numpy as np
    
    a = np.random.random(5)
    print(a.copy())
    print(np.copy(a))
    print(a.view())
    # 会报错
    print(np.view(a))
    
  • 为什么where()不能作为数组ndarray的函数,必须作为NumPy的函数

    import numpy as np
    
    a = np.random.random(10)
    print(np.where(a>0.5))
    # 会报错
    print(a.where(a>0.5))
    

以上这些差异取决于函数在不同的命名空间是否有映射。数组的大部分函数在顶层命名空间有映射,因此可以有两种写法。但数组的一小部分函数没有映射到顶层命名空间,所以只能有一种写法。而顶层命名空间的大部分函数,也都只有一种写法。

3. 数学函数

类别NumPy函数Math模块函数功能
数学常数np.emath.e自然常数
数学常数np.pimath.pi圆周率
舍入函数np.ceil()math.ceil()进尾取整
舍入函数np.floor()math.floor()去尾取整
舍入函数np.around()四舍五入到指定精度
舍入函数np.rint()四舍五入到最近整数
快速转换函数np.deg2rad()np.radians()np.radians()度转弧度
快速转换函数np.rad2deg()np.degrees()math.degrees()弧度转度
幂指数对数函数np.hypot()math.hypot()计算直角三角形的斜边
幂指数对数函数np.square()平方
幂指数对数函数np.sqrt()math.sqrt()开平方
幂指数对数函数np.power()math.pow()
幂指数对数函数np.exp()math.exp()指数
幂指数对数函数np.log()np.log10()np.log2()math.log()math.log10()math.log2()对数
三角函数np.sin()/arcsin()math.sin()/asin()正弦/反正弦
三角函数np.cos()/arccos()math.cos()/acos()余弦/反余弦
三角函数np.tan()/arctan()math.tan()/atan()正切/反正切
import numpy as np
import math

# 两个模块的自然常数相等
print(math.e == np.e)
# 两个模块的圆周率相等
print(math.pi == np.pi)
print(np.ceil(5.3), np.ceil(-5.3))
print(np.floor(5.8), np.floor(-5.8))
print(np.around(5.87, 1))
print(np.rint(5.87))
print(np.degrees(np.pi/2))
print(np.radians(180))
# 求平面上任意两点的距离
print(np.hypot(3,4))
print(np.power(3, 1/2))
print(np.log2(1024))
print(np.exp(1))
# 正弦、余弦函数的周期是2π
print(np.sin(np.radians(30)))
print(np.sin(np.radians(150)))
# 反正弦、反余弦函数的周期则是π
print(np.degrees(np.arcsin(0.5)))

上述代码中使用的函数都是单一的数值,实际上,这些函数也都可以用到NumPy数组上。例如,平面直角坐标系中有1000万个点,他们的x坐标和y坐标都分布在[0,1)区间,哪一个点距离点(0.5,0.5)最近呢?使用Numpy数组计算的代码如下

import numpy as np

p = np.random.random((10000000,2))
# 分离每一个点的x和y坐标
x, y = np.hsplit(p, 2)
# 计算每一个点距离点(0.5,0.5)的距离
d = np.hypot(x-0.5, y-0.5)
# 返回最短距离的点的索引号
i = np.argmin(d)
print('距离点(0.5,0.5)最近的点的坐标是(%f,%f),距离为%f' % (*p[i], d[i]))

4. 统计函数

类别函数功能
查找特殊值np.max/min(a,axis=None)返回最大值/最小值
查找特殊值np.nanmax/nanmin(a, axis=None)忽略nan返回最大值/最小值
查找特殊值np.argmax/argmin(a, axis=None)返回最大值和最小值的索引号
查找特殊值np.nanargmax/nanargmin(a, axis=None)忽略nan返回最大值和最小值索引号
查找特殊值np.median(a, axis=None)返回中位数
查找特殊值np.nanmedian(a, axis=None)忽略nan返回中位数
求和差积np.ptp(a, axis=None)返回元素最大值与最小值的差
求和差积np.sum(a, axis=None)按指定轴求和
求和差积np.nansum(a, axis=None)忽略nan按指定轴求和
求和差积np.cumsum(a, axis=None)按指定周求累计和
求和差积np.nancumsum(a, axis=None)忽略nan按指定轴求累计和
求和差积np.diff(a, axis=None)按指定轴返回相邻元素的差
求和差积np.prod(a, axis=None)按指定轴求积
求和差积np.nanprod(a, axis=None)忽略nan按指定轴返回算数平均值
均值和方差np.mean(a, axis=None)按指定轴返回算数平均值
均值和方差np.nanmean(a, axis=None)忽略nan按指定轴返回算数平均值
均值和方差np.average()返回所有元素的加权平均值
均值和方差np.var(a)返回数组方差
均值和方差np.nanvar(a)忽略nan返回数组方差
均值和方差np.std()返回数组标准差
均值和方差np.nanstd()忽略nan返回数组标准差
相关系数np.corrcoef(a, b)返回a和b的皮尔逊关系数

下面以求最大值和最小值为例,演示忽略np.nan的必要性

import numpy as np
import math

a = np.random.random(10)
print(np.max(a), np.min(a))

a[1::2] = np.nan # 将索引1,3,5,7,9的元素设置为nan
print(a)
print(np.max(a), np.min(a)) # 此时,min()和max()失效了
print(np.nanmax(a), np.nanmin(a)) # 必须使用nanmax()和nanmin()

方差和标准差

import numpy as np
import math

a = np.random.randint(0,50,(3,4))
print(np.sum(np.square(a-a.mean()))/a.size) # 用方差定义求方差
print(np.var(a)) # 直接用方差函数求方差,结果相同

print(np.sqrt(a.var())) # 对方差开方,即是标准差
print(a.std()) # 直接用标准差函数求标准差,结果相同

pa和pb是两只股票连续30个交易日的股价数组。每日股价收益定义为当日股价与前一个交易日股价之差再除以最后一个交易日的股价

import numpy as np
import math

# 综合运用统计函数,分析两只股票的关联关系和收益率

pa = np.array([
    79.66, 81.29, 80.37, 79.31, 79.84, 78.53, 78.29, 78.51, 77.99, 79.82, 
    80.41, 79.27, 80.26, 81.61, 81.39, 80.29, 80.18, 78.38, 75.06, 76.15, 
    75.66, 73.90, 72.14, 74.27, 75.27, 76.15, 75.40, 76.51, 77.57, 77.06
])

pb = np.array([
    30.93, 31.61, 31.62, 31.77, 32.01, 31.52, 30.09, 30.54, 30.78, 30.84, 
    30.80, 30.38, 30.88, 31.38, 31.05, 29.90, 29.96, 29.59, 28.71, 28.95, 
    29.19, 28.71, 27.93, 28.35, 28.92, 29.17, 29.02, 29.43, 29.12, 29.11
])

print(np.corrcoef(pa, pb)) # 两只股票的相关系数为0.867,关联比较密切

pa_re = np.diff(pa)/pa[:-1] # 股价收益率
pb_re = np.diff(pb)/pb[:-1] # 股价与前一个交易日股价差除以最后一个交易日的股价

import matplotlib.pyplot as plt

plt.plot(pa_re)
plt.plot(pb_re)
plt.show()

5. 插值函数

数据插值是数据处理过程中经常用到的技术,常用的插值有一维插值、二维插值、高阶插值等,常见的算法有线性插值、B样条插值、临近插值等。不过,Numpy只提供了一个简单地一维线性插值函数np.interp(),其他更加复杂的插值功能放到了Scipy中。

下面用一个实例来演示NumPy一维线性插值函数的使用方法。假定_x_y是原始的样本点x坐标和y坐标构成的数组,总数只有11个点。如果想在_x的值域范围内插值更多的点,如增加到33个点,就需要在_x的值域范围内生成33个点的x坐标构成的数组x,再利用插值函数np.interp()得到对应的33个点的y坐标构成的数组y。

import numpy as np
import matplotlib.pyplot as plt

_x = np.linspace(0, 2*np.pi, 11)
_y = np.sin(_x)
x = np.linspace(0, 2*np.pi, 33)
y = np.interp(x, _x, _y)

plt.plot(x, y, 'o')
plt.plot(_x, _y, 'o')
plt.show()

6. 多项式拟合函数

拟合又称回归,是指已知某函数的若干离散函数值,通过调整该函数中特定若干待定系数,使得该函数与已知离散函数值的误差达到最小。

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定字体以保证汉字正常显示
plt.rcParams['axes.unicode_minus'] = False # 正确显示连字符

_x = np.linspace(-1, 1, 201)
_y = ((_x**2-1)**3 + 0.5)*np.sin(2*_x) + np.random.random(201)/10 - 0.1

plt.plot(_x, _y, ls='', marker='o', label="原始数据")

for k in range(4, 8):
    g = np.poly1d(np.polyfit(_x, _y, k)) # g是k次多项式
    loss = np.sum(np.square(g(_x)-_y)) # g(x)和f(x)的误差
    plt.plot(_x, g(_x), label="%d次多项式,误差:%0.3f"%(k,loss))
	
plt.legend()
plt.show()

7. 自定义广播函数

7.1 使用np.frompyfunc()定义广播函数

使用np.frompyfunc()将数值函数转换成数组函数需要提供三个参数:数值函数、输入函数的个数和返回值的个数。另外,np.frompyfunc()返回的广播函数,其返回值是object类型,最终需要根据实际情况显式地转换数据类型

import numpy as np

def func_demo(x, y):
    if x == 0 or y == 0 or x == y:
        return 0
    elif x&(x-1) == 0 and y&(y-1) == 0: # x和y都是2的整数次幂
        return max(x, y)
    elif x&(x-1) == 0: # 仅有x等于2的整数次幂
        return x
    elif y&(y-1) == 0: # 仅有y等于2的整数次幂
        return y
    else:
        return max(x, y)

uf = np.frompyfunc(func_demo, 2, 1)
a = np.random.randint(0, 256, (2,5), dtype=np.uint8)
b = np.random.randint(0, 256, (2,5), dtype=np.uint8)
c = uf(a, b)
print(c.dtype) # 此时c的数据类型为object
c = c.astype(np.uint8) # 改变类型
print(c)
7.2 使用np.vectorize()定义广播函数

np.frompyfunc()适用于多个返回值的函数。如果返回值只有一个,使用np.vectorize()定义广播函数更方便,并且还可以通过otypes参数指定返回数组的元素类型

import numpy as np

def func_demo(x, y):
    if x == 0 or y == 0 or x == y:
        return 0
    elif x&(x-1) == 0 and y&(y-1) == 0: # x和y都是2的整数次幂
        return max(x, y)
    elif x&(x-1) == 0: # 仅有x等于2的整数次幂
        return x
    elif y&(y-1) == 0: # 仅有y等于2的整数次幂
        return y
    else:
        return max(x, y)
uf = np.vectorize(func_demo, otypes=[np.uint8])
c = uf(a, b)
print(c) # 此时c的数据类型为uint8

自定义广播函数并不是真正的广播函数,其运行效率和循环遍历几乎没有差别,因此除非确实必要,否则不应该滥用自定义广播函数。

相关文章:

  • 字符串常量池与StringBuilder
  • 时间序列中的特征选择:在保持性能的同时加快预测速度
  • 谷粒商城 (九) --------- 前端基础 Vue 篇
  • MySQL锁机制详解-表锁与行锁
  • mysql行锁,表锁,间隙锁
  • 【GEE笔记11】数值Number(常见指令方法4)
  • Linux_进程概念
  • 【PAT乙】2022秋季赛后总结
  • nginx + tomcat 搭建负载均衡、动静分离(tomcat多实例)
  • CSRF(跨站请求伪造)攻击和预防
  • 【都 Java17 了,还不了解 Java 8 ? 】一文带你深入了解 Java 8 新特性
  • 解决国产机SVN连接失败的问题
  • MySQL 存储过程创建指定表结构
  • 我们这样的人
  • < Linux > 进程概念(2)
  • [译]前端离线指南(上)
  • 【React系列】如何构建React应用程序
  • Java Agent 学习笔记
  • Magento 1.x 中文订单打印乱码
  • Markdown 语法简单说明
  • vue--为什么data属性必须是一个函数
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 我是如何设计 Upload 上传组件的
  • NLPIR智能语义技术让大数据挖掘更简单
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • 数据库巡检项
  • ​Python 3 新特性:类型注解
  • #考研#计算机文化知识1(局域网及网络互联)
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (二)换源+apt-get基础配置+搜狗拼音
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (四)Controller接口控制器详解(三)
  • (一) springboot详细介绍
  • (一)认识微服务
  • .“空心村”成因分析及解决对策122344
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .htaccess配置重写url引擎
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .net 程序发生了一个不可捕获的异常
  • .NET4.0并行计算技术基础(1)
  • .NET成年了,然后呢?
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • /usr/bin/env: node: No such file or directory
  • @Builder用法
  • [100天算法】-每个元音包含偶数次的最长子字符串(day 53)
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——
  • [BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)
  • [CSDN首发]鱿鱼游戏的具体玩法详细介绍
  • [CTF]php is_numeric绕过
  • [Nginx]反向代理Node将3000端口访问转换成80端口
  • [Python]闭包
  • [Repo Git] manifests的写法