目录
一、numpy特殊值
NumPy有两个很有趣的特殊值,np.nan 和 np.inf。nan 是 not a number 的简写,意为不是数字,inf 是 infinity 的简写,意为无穷大。np.nan 也可以写作 np.Nan、np.NaN 或者 np.NAN,np.inf 也可以写作 np.Inf 或 np.Infinity。
numpy提供了判断是否为nun和inf的方法:
import numpy as np
a = np.array([1,np.nan,np.inf])
for value in a:
print(value,np.isnan(value)) #判断是否是nan
print(value,np.isinf(value)) #判断是否是inf
NumPy 用特殊值来表示缺值、空值和无效值。想一想,Python 和 C 语言如何表示数组中的缺值、空值和无效值呢?Python 因为数组元素不受类型限制,可以用 None 或者 False 等表示缺值、空值和无效值。对 C 语言来说,恐怕也只能在数据的值域范围之外,选一个特定值来表示吧?比如,假定数组存储的是学生的成绩,成绩一般都是正值,所以C语言可以用-1表示缺考。在NumPy数组中,因为有了nan和inf这两个特殊值,我们就不用在意数据的值域范围了。numpy的这两个特殊值,一个不是数字,一个无穷大,数组运算的时候怎么处理呢?这就是NumPy神奇的地方,我们根本不用担心这个问题,因为并不影响数值计算。
比如:
a = np.array([9, 3, np.nan, 5, 3])
print(np.mean(a))
print(a)
a = np.repeat(a,2)[:-1] #去掉最后一个元素
print(a[1::2])
a[1::2] += (a[2::2]-a[1::2])/2 #加上相邻的算术平均值
print(a[1::2])
print(a)
得到结果:
nan
[ 9. 3. nan 5. 3.]
[ 9. 3. nan 5.]
[ 6. nan nan 4.]
[ 9. 6. 3. nan nan nan 5. 4. 3.]
二、 函数命名空间
数组的大部分函数在顶层命名空间有映射,因此可以有两种用法。数组的一小部分函数,没有映射到顶层命名空间,只能有一种用法。而顶层命名空间的大部分函数,也都只有一种用法。
三、数学函数
math和numpy常用的数学函数分为以下几类:
-
数学常数
-
舍入函数
-
快速转换函数
-
幂函数、指数函数和对数函数
-
部分三角函数
常见函数如下:
四、统计函数
NumPy 的统计函数有很多,大约可以分成4类:
-
查找特殊值
-
求和差积
-
均值和方差
-
相关系数
常用函数如下:
五、差值函数
数据插值是数据处理过程中经常用到的技术,常用的插值有一维插值、二维插值、高阶插值等,常见的算法有线性插值、B样条插值、临近插值等。不过,NumPy只提供了一个简单的一维线性插值函数 np.interp(),其他更加复杂的插值功能放到了SciPy中。
以下是使用interp()方法的示例:
_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()
六、多项式拟合函数
拟合又称回归,是指已知某函数的若干离散函数值,通过调整该函数中若干待定系数,使得该函数与已知离散函数值的误差达到最小。
NumPy提供了一个非常简单易用的多项式拟合函数np.polyfit(),只需要输入一组自变量的离散值,和一组对应的函数 f ( x ) ,并指定多项式次数 k,就可以返回一组最佳系数。函数np.polyfit(),则可以将一组最佳系数转成函数 g(x)。
以下是polyfit方法的使用示例:
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()
七、 自定义广播函数
广播是NumPy最具特色的特性之一,几乎所有的NumPy函数都可以通过广播特性将操作映射到数组的每一个元素上。然而NumPy函数并不能完成所有的工作,有些工作还需要我们自己来定义函数。如何让我们自己定义的函数也可以广播到数组的每一个元素上,就是自定义广播函数要做的事情。
这里有一个自定义的函数功能:
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)
有两种方式将自定义的函数转化为传播函数
7.1 使用np.frompyfunc定义传播函数
使用 np.frompyfunc( ) 将数值函数转换成数组函数需要提供三个参数:数值函数、输入参数的个数和返回值的个数。另外,np.frompyfunc() 返回的广播函数,其返回值是object类型,最终需要根据实际情况显式地转换数据类型,其代码如下。
uf = np.frompyfunc(func_demo, 2, 1)
x = np.random.randint(0,10,20)
y = np.random.randint(0,10,20)
print(uf(x,y))
7.2 使用np.vectorize定义广播函数
np.frompyfunc( ) 适用于多个返回值的函数。如果返回值只有一个,使用 np.vectorize( ) 定义广播函数更方便,并且还可以通过 otypes 参数指定返回数组的元素类型,其代码如下。
uf = np.vectorize(func_demo, otypes=[np.uint8])
x = np.random.randint(0,10,20)
y = np.random.randint(0,10,20)
print(uf(x,y))
注意:
自定义广播函数并不是真正的广播函数,其运行效率和循环遍历几乎没有差别,因此除非确实必要,否则不应该滥用自定义广播函数。