一,处理NAN数据

1、数组里面有NAN数据,如何处理:一种用0替换,另一种用该列平均值替换

注意:float类型的数据才能赋值nan
思路:
1)取出数组的所有列
2)判断该列中有没有NAN数据(使用NAN!=NAN的方式)
3)若该列存在NAN数据,则取出该列不为NAN的数据(为了计算平均值)
4)使用该列平均值将NAN数据替换
5)循环以上步骤

PS:np.nan != np.nan 结果是True,利用其特性对nan数据进行处理

t= np.arange(24).reshape(4,6).astype('float')
#构造几个元素为NAN
t[1,3:]=np.nan
print(t)
#通过t.shape可得到数组的行数与列数,再取[1]得到列数
for i in range(t.shape[1]):
	#循环取出列
    l=t[:,i]
    #计算含有NAN元素的列个数
    nan_num=np.count_nonzero(l!=l)
    #若含有NAN,继续执行
    if nan_num != 0:
    	#取出该列不为NAN的元素
        l_notnan=l[l==l]
        print(l_notnan)
        将该列中为nan的元素替换为该列其他元素的平均值
        l[np.isnan(l)]=np.mean(l_notnan)
print(t)

[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. nan nan nan]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. 21. 22. 23.]]
[ 3. 15. 21.]
[ 4. 16. 22.]
[ 5. 17. 23.]
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 13. 14. 15.]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. 21. 22. 23.]]

2、理解根据条件修改或取出数组中的值

  • 数组
t=np.arange(24).reshape(4,6)
#用t与int数组比较时,使用的是数组内的每个元素去对比,把符合的元素重新赋值
t[t<10]=0
print(t)
#用数组t与本身比较时,是用对应位置的元素去比较,由于t中不含nan元素,故t==t所有元素均满足
t[t==t]=2
print(t)
print(type(t))

[[ 0 0 0 0 0 0]
[ 0 0 0 0 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[2 2 2 2 2 2]
[2 2 2 2 2 2]
[2 2 2 2 2 2]
[2 2 2 2 2 2]]
<class ‘numpy.ndarray’>

-----数组还可以进行如下逻辑判断方式修改元素值

t[(t<2)&(t>8)]=0
  • 列表
    而对于列表,比对的时候type是list与int的对比,会有语法错误
array=[1,2,3,4,5]
#此处的对比是逻辑运算,array这个列表不等于3是True,其值也为1.那么下面代码即为取出array的index为1的元素赋值为0.
array[array != 3]=0
#array[array < 3]=0
print(array)
print(array!=array)
print(type(array))

[1, 0, 3, 4, 5]
False
<class ‘list’>

array=[1,2,3,4,5]
#array[array != 3]=0
#此处使用列表和数值3进行运算,是不可以的
array[array < 3]=0
print(array)
print(array!=array)
print(type(array))

File “D:/untitled1/numpy.py”, line 98, in
True
array[array < 3]=0
[[ 0. 1. 2. 3. 4. 5.]
TypeError: ‘<’ not supported between instances of ‘list’ and ‘int’

二、numpy数组切片后赋给新数组,改变新数组元素值时,原数组也随之改变

1、浅拷贝
请注意上述代码中,倒数第二行,替换nan元素时,使用的是l数组(原t数组切片得到的),但是最终输出原数组t的值时,t中nan也随l数组改写了。

import numpy as np
t= np.arange(24).reshape(4,6).astype('float')
#切片并赋值给新数组
line=t[:,1:]
print(line)
print(t)
print("*"*20)

#修改切片后数组中的元素值
line[line>6]=0
print(line)
#可以看到原数组t的值也改变了
print(t)

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


[[1. 2. 3. 4. 5.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 0. 0. 0. 0. 0.]
[12. 0. 0. 0. 0. 0.]
[18. 0. 0. 0. 0. 0.]]

结论:切片后的变量与原始的数据共享同一数据存储,为浅拷贝

2、深拷贝
如何解决原数组随之更改的情形:
使用narray.copy()进行深拷贝,即拷贝numpy对象中的数据,而不是地址

import numpy as np
t= np.arange(24).reshape(4,6).astype('float')
#切片后添加copy()
line=t[:,1:].copy()

print(line)
print(t)
print("*"*20)
line[line>6]=0

print(line)
print(t)

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


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

浅拷贝运算快,内存占用少,但是缺点也很明显:拷贝出来的对象和原对象不独立。实际运用中根据自己的需要来选择具体使用哪种方法进行拷贝。