numpy中的nan和inf,及其批量判别、替换方式
作者:domodo2012
在Numpy中,NaN表示非数值,Inf表示无穷大,NaN与任何值计算都是NaN,Inf与0相乘是NaN,其余情况下与Inf运算仍为Inf,可以使用np.isnan(), np.isinf(), np.isneginf(), np.isposinf(), np.isfinite()等函数进行批量判别,返回布尔值数组
1、概念
nan
:not a number (非数值)inf
:infinity (inf:正无穷,-inf:负无穷 ),下文中的 inf 包含了两种无穷numpy 中,nan 和 inf 的类型都是 float 。
2、性质
2-1、多个 nan 之间的比较,地址相等,值不相等
import numpy as np print(f'nan 之间的值比较 {np.nan == np.nan}') print(f'nan 之间的地址比较 {np.nan is np.nan}')
Out[18]: nan 之间的值比较 False nan 之间的地址比较 True
2-2、nan 与任何值的计算,结果都是 nan
2-3、多个 inf 之间的比较,地址相等,值相等
print(f'inf 之间的值比较 {np.inf == np.inf}') print(f'inf 之间的地址比较 {np.inf is np.inf}')
Out[19]: inf 之间的值比较 True inf 之间的地址比较 True
2-4、0乘以 inf 结果是 nan,其他与 inf 做的简单加、乘运算,结果都是 inf
In[20]: 0 * np.inf Out[20]: nan
In[21]: 2341 * np.inf Out[21]: inf In[22]: -241 + np.inf Out[21]: inf
2-5、inf 外的其他数除以 inf,结果是0,inf 除以 inf,结果是 nan
In[22]: 894 / np.inf Out[22]: 0.0 In[23]: np.inf / np.inf Out[23]: nan
2-6、所有数都比 -inf 大 所有数都比 +inf 小,+inf 和 +inf 相等,-inf 和 -inf 相等
In[24]: 1.0e-28 > -np.inf Out[24]: True In[25]: 1.e+43 < np.inf Out[25]: True In[26]: np.inf == np.inf True In[27]: -np.inf == -np.inf Out[27]: True
3、数组中 nan、inf 的批量判别
np.isnan()
:批量判别数组中每个元素是否为 nannp.isinf()
:批量判别数组中每个元素是否为 infnp.isneginf()
:批量判别数组中每个元素是否为 +infnp.isposinf()
: 批量判别数组中每个元素是否为 -infnp.isfinite()
:批量判别数组中每个元素是否为非 inf 非 nan 的值
以上的返回值都是与被判别数组同维度的 bool 值数组
In[30]: a1 = np.array([[1, np.nan, np.inf], [np.nan, -np.inf, -0.25]]) print(a1) print(np.isfinite(a1)
Out[30]: array([[ 1. , nan, inf], [ nan, -inf, -0.25]]) array([[ True, False, False], [False, False, True]])
4、数组中 nan、inf 的批量替换
4-1、数组中 nan、inf 值的批量替换
In[31]: a = np.array([[np.nan, np.nan, 1, 2], [np.inf, np.inf, 3, 4], [1, 1, 1, 1], [2, 2, 2, 2]]) print('替换前') print (a) where_are_nan = np.isnan(a) where_are_inf = np.isinf(a) #nan替换成0,inf替换成nan a[where_are_nan] = 0 a[where_are_inf] = np.nan print('替换后') print(a)
Out[31]: 替换前 [[nan nan 1. 2.] [inf inf 3. 4.] [ 1. 1. 1. 1.] [ 2. 2. 2. 2.]] 替换后 [[ 0. 0. 1. 2.] [nan nan 3. 4.] [ 1. 1. 1. 1.] [ 2. 2. 2. 2.]]
4-2、nan值替换成每列的均值
In[32]: def fill_ndarray(t1): for i in range(t1.shape[1]): # 遍历每一列(每一列中的nan替换成该列的均值) temp_col = t1[:, i] # 当前的一列 nan_num = np.count_nonzero(temp_col != temp_col) if nan_num != 0: # 不为0,说明当前这一列中有nan temp_not_nan_col = temp_col[temp_col == temp_col] # 去掉nan的ndarray # 选中当前为nan的位置,把值赋值为不为nan的均值 temp_col[np.isnan(temp_col)] = temp_not_nan_col.mean() # mean()表示求均值。 return t1 if __name__ == '__main__': t1 = np.array([[ 0., 1., 2., 3., 4., 5.], [ 6., 7., np.nan, np.nan, np.nan, np.nan], [12., 13., 14., 15., 16., 17.], [18., 19., 20., 21., 22., 23.]]) print('替换前') print(t1) t1 = fill_ndarray(t1) # 将nan替换成对应的均值 print('替换后') print(t1)
Out[32]: 替换前 [[ 0. 1. 2. 3. 4. 5.] [ 6. 7. nan nan nan nan] [12. 13. 14. 15. 16. 17.] [18. 19. 20. 21. 22. 23.]] 替换后 [[ 0. 1. 2. 3. 4. 5.] [ 6. 7. 12. 13. 14. 15.] [12. 13. 14. 15. 16. 17.] [18. 19. 20. 21. 22. 23.]]
替换成行均值的类似处理即可。
4-3、inf替换成每列的均值
先把所有 inf 都换成 nan,之后参照 3-2 处理即可。
4-4、numpy.nan_to_num(x)
使用说明:用 0 代替数组 x 中的 nan,用有限值代替 inf
In[33]: a = np.array([[np.nan,np.inf], [-np.nan,-np.inf]]) np.nan_to_num(a)
Out[33]: array([[ 0.00000000e+000, 1.79769313e+308], [ 0.00000000e+000, -1.79769313e+308]])
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。