numpy中的nan和inf

numpy中的nan和inf

  • numpy中有两个特殊数值nan 和 inf

一、nan和inf

1. nan

  • nan全称为 not a number ,表示不是一个数字
  • 对于nan,任何数值(包括其本身)和它的比较都是false的结果,因为nan不等于任何值
  • 什么时候数组中会出现nan:
    • 当我们读取本地文件为float的时候,如果某些位置有缺失的数据,就会用nan代替
    • 当做了一个不合适的计算的时候(比如无穷大(inf)减去无穷大)

2. inf

  • inf ,全称为 infinity,表示无穷大的意思,分为 -inf 和 +inf(加号可以省略),分别表示正无穷大和负无穷大

  • 对于inf,任何有限数都比它小,因为inf是正无穷大的意思,对于-inf,任何有限数都大于它

  • 什么时候数组中会出现inf:

    • 当一个数字除以0,python中会直接报错,但是在numpy中结果是一个inf或者 -inf

3. 如何赋值为nan、inf

import numpy as np

t = np.nan
print(t)
print(type(t))
print('*'*30)
t1 = np.inf
print(t1)
print(type(t1))

nan
<class 'float'>
******************************
inf
<class 'float'>
  • 因为numpy数组中的数值类型都是一致的,所以当我们想改变其中的值为nan或inf时,首先应该要知道nan、inf的数值类型到底属于哪种
  • 从上面的代码可以看到,nan和inf都属于float类型,可以通过numpy.nan 和 numpy.inf来对一个变量直接进行赋值,当对数组进行改值时,首先需要将数组的数值类型转换为float,即 ndarray.astype('float')

二、nan的特性

  • 两个nan是不相等的,利用这个特性,可以统计数组中nan的个数
  • 无论何值,和nan进行计算时,其结果都为nan

1. 比较两个nan和两个inf

# 1. 两个nan是不相等的
print("nan==nan:", np.nan==np.nan)
print("nan!=nan:", np.nan!=np.nan)

"""
nan==nan: False
nan!=nan: True
"""

2. inf自身的比较
print(np.inf > np.inf)
print(np.inf < np.inf)
print(np.inf == np.inf)
print((-np.inf) > (-np.inf))
print((-np.inf) < (-np.inf))
print((-np.inf) == (-np.inf))
 
"""
False
False
True
False
False
True
"""    

2. 统计数组中的非0元素个数

  • 语法:numpy.count_nonzero(数组)
    • 该方法虽然统计的是非0的个数,其实统计的是非假的个数,即非false的元素个数
    • 在python中,0也是假
t = np.arange(24).reshape(4, 6)
t[:,0] = 0  # 将第一列变为0
print(t)

print(np.count_nonzero(t))  # 20

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

3. 将数组中的元素赋值为nan

  • 前面我们提到,nan和inf都是float类型,所以要将数组中的元素变为nan,首先要确保数组的数值类型为float

t = np.arange(24).reshape(4, 6)
t[:,0] = 0  # 将第一列变为0
print(t)
print(np.count_nonzero(t))  # 20

print("*"*50)

t = t.astype('float')  # 改变数组的数值类型为float
t[2,3] = np.nan  # 将坐标(2,3)的值变为 nan
print(t)

"""
[[ 0  1  2  3  4  5]
 [ 0  7  8  9 10 11]
 [ 0 13 14 15 16 17]
 [ 0 19 20 21 22 23]]
20
**************************************************
[[ 0.  1.  2.  3.  4.  5.]
 [ 0.  7.  8.  9. 10. 11.]
 [ 0. 13. 14. nan 16. 17.]
 [ 0. 19. 20. 21. 22. 23.]]
"""

4. 统计数组中nan的个数

  • 利用上面提到的两个nan不相等的特性,以及统计数组中非0个数的方法,即可统计出数组中nan的个数
  • 也可以通过下面 isnan()的方法来比较后统计个数
t = np.arange(24).reshape(4, 6)
t[:,0] = 0  # 将第一列变为0
print(t)
print(np.count_nonzero(t))  # 20

print("*"*50)

t = t.astype('float')  # 改变数组的数值类型为float
t[2,3] = np.nan  # 将坐标(2,3)的值变为 nan
print(t)

print("*"*50)

t1 = t != t
print(t1)
print(np.count_nonzero(t1))  # 同 print(np.count_nonzero(t != t))

"""
[[ 0  1  2  3  4  5]
 [ 0  7  8  9 10 11]
 [ 0 13 14 15 16 17]
 [ 0 19 20 21 22 23]]
20
**************************************************
[[ 0.  1.  2.  3.  4.  5.]
 [ 0.  7.  8.  9. 10. 11.]
 [ 0. 13. 14. nan 16. 17.]
 [ 0. 19. 20. 21. 22. 23.]]
**************************************************
[[False False False False False False]
 [False False False False False False]
 [False False False  True False False]
 [False False False False False False]]
1
"""

5. 判断一个值是否为nan

  • 语法:numpy.isnan()
  • 用这个方法同样能得到上面 t!=t 的结果
t = np.arange(24).reshape(4, 6)
t[:,0] = 0  # 将第一列变为0
print(t)
print(np.count_nonzero(t))  # 20

print("*"*50)

t = t.astype('float')  # 改变数组的数值类型为float
t[2,3] = np.nan  # 将坐标(2,3)的值变为 nan
print(t)

print("*"*50)

t1 = t != t
print(t1)
# print(np.count_nonzero(t1))
print(np.count_nonzero(t != t))

print("*"*50)

t2 = np.isnan(t)  # 判断数组中每个元素的值是否是nan
print(t2)
print(np.count_nonzero(t2))  # 同 print(np.count_nonzero(np.isnan(t))) 

"""
[[ 0  1  2  3  4  5]
 [ 0  7  8  9 10 11]
 [ 0 13 14 15 16 17]
 [ 0 19 20 21 22 23]]
20
**************************************************
[[ 0.  1.  2.  3.  4.  5.]
 [ 0.  7.  8.  9. 10. 11.]
 [ 0. 13. 14. nan 16. 17.]
 [ 0. 19. 20. 21. 22. 23.]]
**************************************************
[[False False False False False False]
 [False False False False False False]
 [False False False  True False False]
 [False False False False False False]]
1
**************************************************
[[False False False False False False]
 [False False False False False False]
 [False False False  True False False]
 [False False False False False False]]
1
"""

三、数组”约减“(聚合)操作中nan的影响

  • 这里拿求和sum()方法来举例

  • 由于无论何值,和nan进行运算时,其结果都为nan。此时,有两种办法,1将nan替换为其他值,2删除掉nan所在的行或列

  • 在一组数据中单纯的把nan替换为0并不合适。全部替换为0后,替换之前的平均值如果大于0,替换之后的均值肯定会变小,所以更一般的方式是把缺失的数值替换为均值(中值)或者是直接删除有缺失值的一行

  • 示例

# nan缺失值填充均值

t1 = np.arange(12).reshape((3, 4)).astype("float")
print('t1')
print(t1.size)  # 获取数组中所有的元素个数,相当于ndarray.shape中 m*n的值
print(t1)
print('t1_sum1',t1.sum())

t1[1, 2:] = np.nan  # 将数组中第二行中的第2列到最后列变为nan
print('t1')
print(t1)
print('t1_sum2',t1.sum())  # nan与其他所有数值的运算结果都为nan
print("*"*50)
# 遍历每一列并计算每一列的nan数量
for i in range(t1.shape[1]):
    temp_col = t1[:,i]
    nan_num = np.count_nonzero(temp_col != temp_col)  # 该列中nan的数量
    # 若存在nan, 则求不含nan的均值, 并将nan赋值为均值
    if nan_num != 0:
        temp_not_nan_col = temp_col[temp_col == temp_col]  # 获取该列中不是nan的部分
        temp_col[np.isnan(temp_col)] = temp_not_nan_col.mean()  # 将该列中nan的部分改为该列的均值
print(t1)


"""
t1
12
[[ 0.  1.  2.  3.]
 [ 4.  5.  6.  7.]
 [ 8.  9. 10. 11.]]
t1_sum1 66.0
t1
[[ 0.  1.  2.  3.]
 [ 4.  5. nan nan]
 [ 8.  9. 10. 11.]]
t1_sum2 nan
**************************************************
[[ 0.  1.  2.  3.]
 [ 4.  5.  6.  7.]
 [ 8.  9. 10. 11.]]
"""
posted @ 2025-03-12 16:34  BigSun丶  阅读(418)  评论(0)    收藏  举报