目的

  1.查找NaN值(定位到哪一列、在列的哪个索引位置)

  2.填充NaN值(向上填充、向下填充、线性填充等)

  3.过滤NaN值

构建简单的Dataframe数据结构环境

import pandas as pd
import numpy as np #在df中nan和None都会被自动填充为NaN
df=pd.DataFrame({'a':[np.nan,1,2,3],'b':[None,5,6,7],'c':[8,9,10,11]})
print(df) '''结果
a b c
0 NaN NaN 8
1 1.0 5.0 9
2 2.0 6.0 10
3 3.0 7.0 11 '''

注意点:

  1.None、nan在构建dataframe数据结构中都会被识别为NaN

  2.None与nan的类型是不一样的

#nan是个特殊的float类型
print(type(np.nan)) #<class 'float'> #None是NoneType
print(type(None)) #<class 'NoneType'>
#打印空值看输出结果
print(df['a'][0]) #nan
#作为字典的key时,会被认为是不同的key
dic={None:1, NaN:2}
print(dic) #{None: 1, nan: 2}

目的1:查找NaN值

原始数据:

df=pd.DataFrame({'a':[0,1,np.nan,3,4],'b':[4,5,6,np.nan,8],'c':[9,10,np.nan,np.nan,13]})
print(df) '''结果
a b c
0 0.0 4.0 9.0
1 1.0 5.0 10.0
2 NaN 6.0 NaN
3 3.0 NaN NaN
4 4.0 8.0 13.0 '''

1.1 输出NaN值所在具体位置(调用math下面的isnan做判断)

from math import isnan
for i in df.columns:
# print(df[i].values)
for k in range(len( df[i].values)):
if isnan(df[i].values[k]):
print('字段%s存在NaN值:' % i + '索引位置是:%s'%k)

1.2 分别找到NaN值所在的列名、行名:np.isnan()

import pandas as pd
import numpy as np
from math import isnan #在df中nan和None都会被自动填充为NaN
df=pd.DataFrame({'a':[np.nan,1,2,3,4],'b':[4,5,6,np.nan,np.nan],'c':[9,10,np.nan,np.nan,np.nan]},index=['index_0','index_1','index_2','index_3','index_4'])
print(df)
'''原始数据
a b c
index_0 NaN 4.0 9.0
index_1 1.0 5.0 10.0
index_2 2.0 6.0 NaN
index_3 3.0 NaN NaN
index_4 4.0 NaN NaN
'''
#利用np.isnan(df),对整个df的NaN值做判断
res=np.isnan(df)
print(res)
'''
a b c
index_0 True False False
index_1 False False False
index_2 False False True
index_3 False True True
index_4 False True True ''' nan_res=np.where(np.isnan(df))
print(nan_res) #(array([0, 2, 3, 3, 4, 4], dtype=int32), array([0, 2, 1, 2, 1, 2], dtype=int32))
'''
#得到一个元祖
(array([0, 2, 3, 3, 4, 4], dtype=int32), array([0, 2, 1, 2, 1, 2], dtype=int32))
元祖第一个值:表示行索引(都是以数字表示)
元祖第二个值:表示列索引(都是以数字表示)
注意:看前后行、列索引列表的排序,发现是每一行的数据去逐一检索的
''' #查看NaN值默认行号(数字)(有重复值时表示是这一行里有多个NaN值)
print(nan_res[0]) #[0 2 3 3 4 4]
print(nan_res[1]) #[0 2 1 2 1 2] #查看NaN值的行号名(即实际行号名字)
nan_index_info=df.index[np.where(np.isnan(df))[0]]
print(nan_index_info) #Index(['index_0', 'index_2', 'index_3', 'index_3', 'index_4', 'index_4'], dtype='object') #查看NaN值的列名
nan_columns_info=df.columns[np.where(np.isnan(df))[1]]
print(nan_columns_info) #Index(['a', 'c', 'b', 'c', 'b', 'c'], dtype='object')

1.3 isnull、notnull

isnull_res=df.isnull()
print(isnull_res)
'''
a b c
0 False False False
1 False False False
2 True False True
3 False True True
4 False False False '''

1.4 isnull().values

# 2.1 isnull().values
isnull_res=df.isnull().values
print(isnull_res)
'''
[[False False False]
[False False False]
[ True False True]
[False True True]
[False False False]] '''

1.5 isnull().sum() 统计显示

#2.3 isnull().sum() 统计
isnull_res=df.isnull().sum()
print(isnull_res)
'''
a 1
b 1
c 2
dtype: int64 '''

1.6 isnull().any() 布尔值,显示行里是不是有NaN值

df=pd.DataFrame({'a':[0,1,np.nan,3,4],'b':[4,5,6,np.nan,8],'c':[9,10,np.nan,np.nan,13]})
print(df)
'''原始数据
a b c
0 0.0 4.0 9.0
1 1.0 5.0 10.0
2 NaN 6.0 NaN
3 3.0 NaN NaN
4 4.0 8.0 13.0 ''' any_res=df.isnull().any()
print(any_res)
'''
a True
b True
c True
dtype: bool '''

目的2:填充NaN值

原始数据样子:

df=pd.DataFrame({'a':[0,1,np.nan,3,4],'b':[4,5,6,np.nan,8],'c':[9,10,np.nan,np.nan,13]})
print(df) '''结果
a b c
0 0.0 4.0 9.0
1 1.0 5.0 10.0
2 NaN 6.0 NaN
3 3.0 NaN NaN
4 4.0 8.0 13.0 '''

2.1 fillna直接填充

#2.1.fillna直接填充
df.fillna(0,inplace=True) #表示更新到源数据
print(df)
'''
a b c
0 0.0 4.0 9.0
1 1.0 5.0 10.0
2 0.0 6.0 0.0
3 3.0 0.0 0.0
4 4.0 8.0 13.0 ''' #另外一种方式
res=df.where(df.notna(),100)

fillna({字典}),字典key:表示列索引  value:表示要填充的值

df=pd.DataFrame({'a':[0,1,2,3,4],'b':[4,5,6,np.nan,8],'c':[9,10,np.nan,np.nan,13]})

#意为将b列空值:填充为00 c列空值填充为:11
df_new=df.fillna({'b':00,'c':11})
print(df_new)
'''
a b c
0 0 4.0 9.0
1 1 5.0 10.0
2 2 6.0 11.0
3 3 0.0 11.0
4 4 8.0 13.0 '''

2.2 向上填充(即取NaN后面一个数值作为填充):bfill

fillna_res=df.fillna(method='bfill')
print(fillna_res)
'''
a b c
0 0.0 4.0 9.0
1 1.0 5.0 10.0
2 3.0 6.0 13.0
3 3.0 8.0 13.0
4 4.0 8.0 13.0 '''

2.3 向下填充(即取NaN前面一个数值作为填充):ffill

fillna_res=df.fillna(method='ffill')
print(fillna_res)
'''
a b c
0 0.0 4.0 9.0
1 1.0 5.0 10.0
2 1.0 6.0 10.0
3 3.0 6.0 10.0
4 4.0 8.0 13.0 '''

2.4 用一个数据代替NaN:pad  (功能类似于向下填充ffill)

fillna_res=df.fillna(method='pad')
print(fillna_res)
'''
a b c
0 0.0 4.0 9.0
1 1.0 5.0 10.0
2 1.0 6.0 10.0
3 3.0 6.0 10.0
4 4.0 8.0 13.0 '''

2.5 平均值替换:df.mean()

#平均值替换:df.mean()
fillna_res=df.fillna(df.mean())
print(fillna_res)
'''
a b c
0 0.0 4.00 9.000000
1 1.0 5.00 10.000000
2 2.0 6.00 10.666667
3 3.0 5.75 10.666667
4 4.0 8.00 13.000000 '''

2.6 指定替换具体列的NaN值

#选择指定替换哪些列
choose_fillna=df.fillna(df.mean()['a':'b'])
print(choose_fillna)
'''
a b c
0 0.0 4.00 9.0
1 1.0 5.00 10.0
2 2.0 6.00 NaN
3 3.0 5.75 NaN
4 4.0 8.00 13.0 '''

2.7 限制每列替换NaN的个数:limit=

limit_res=df.fillna(df.mean(),limit=1)
print(limit_res)
'''
a b c
0 0.0 4.00 9.000000
1 1.0 5.00 10.000000
2 2.0 6.00 10.666667
3 3.0 5.75 NaN
4 4.0 8.00 13.000000 '''

2.8  线性插值 df.interpolate(),如果存在第一个值是NaN的情况,这个NaN值无法被替换,需要单独再判断

df=pd.DataFrame({'a':[2,1,2,3,4],'b':[4,5,6,np.nan,2],'c':[9,10,np.nan,np.nan,4]},index=['index_0','index_1','index_2','index_3','index_4'])
print(df)
'''
a b c
index_0 2 4.0 9.0
index_1 1 5.0 10.0
index_2 2 6.0 NaN
index_3 3 NaN NaN
index_4 4 2.0 4.0 '''
#实际上上前一个值和后一个值得平均数,因为interpolate()假设函数是直线形式
print(df.interpolate())
'''
a b c
index_0 2 4.0 9.0
index_1 1 5.0 10.0
index_2 2 6.0 8.0
index_3 3 4.0 6.0
index_4 4 2.0 4.0 '''

特殊情况的填充:

  重点:假设每一列数据的第一或最后为空(再用上面的普通方法就填充时就容易忽略掉1和最后的值)

解决思路:

#解决的一个问题是开头和结果都是NaN的情况
1.判断如果开头是NaN取下面最近的数值填充
2.如果结尾是NaN取上面最近的数值填充
3.最后再对整体的中间NaN进行替换,就可以向上或向下取值了代码 

初始数据结构:

df=pd.DataFrame({'a':[np.nan,1,np.nan,3,4],'b':[None,5,np.nan,7,None],'c':[9,10,np.nan,12,13]})
print(df)
df=pd.DataFrame({'a':[np.nan,1,np.nan,3,4],'b':[None,5,np.nan,7,None],'c':[9,10,np.nan,12,13]})
print(df)
'''
a b c
0 NaN NaN 9.0
1 1.0 5.0 10.0
2 NaN NaN NaN
3 3.0 7.0 12.0
4 4.0 NaN 13.0 '''

代码实现3个步骤:

#循环没一个列的value值(判断)
for i in df.columns:
n=1
for k in range(len(df[i].values)):
#如果第一个值是NaN
if isnan(df[i].values[0]):
#找下面最近的不是NaN的值做填充
if not isnan(df[i].values[k]):
df[i].values[0]=df[i].values[k] # print('说明第一个值是0,要替换成下面离他最近的一个数值') #如果最后一个值是NaN
elif isnan(df[i].values[len(df[i].values)-1]):
n+=1
#再判断倒数第二个值看是否是NaN(依次往上找,找到不是NaN的值做替换)
if not isnan(df[i].values[len(df[i].values)-n]):
df[i].values[len(df[i].values) - 1]=df[i].values[len(df[i].values)-n] # print('说明最后一个值是0,要替换成上面离他最近的一个数值') #最终对整体没一列中存在的NaN数据进行向前取值
df=df.fillna(method='pad') print(df)

目的3:过滤NaN值

初始数据

df=pd.DataFrame({'a':[0,1,2,3,4],'b':[4,5,6,np.nan,8],'c':[9,10,np.nan,np.nan,13]})
print(df)
'''
a b c
0 0 4.0 9.0
1 1 5.0 10.0
2 2 6.0 NaN
3 3 NaN NaN
4 4 8.0 13.0 '''

3.1 删除存在NaN的行或列:dropna()

#默认删除存在NaN的行:
# res=df.dropna()
# print(res)
'''
a b c
0 0 4.0 9.0
1 1 5.0 10.0
4 4 8.0 13.0 '''

3.2 删除存在NaN的列:axis=1

res=df.dropna(axis=1) #删除存在NaN的列
print(res)
'''
a
0 0
1 1
2 2
3 3
4 4 '''

3.3 删除全为NaN的how='all'

#删除全为NaN的行
all_res=df.dropna(how='all')
print(all_res)

3.4 删除全为NaN的列(axis=1,how='all')

#删除全为NaN的列(axis=1,how='all')
df=pd.DataFrame({'a':[0,1,2,np.nan,4],'b':[4,5,6,np.nan,8],'c':[np.nan,np.nan,np.nan,np.nan,np.nan]})
print(df)
'''
a b c
0 0.0 4.0 NaN
1 1.0 5.0 NaN
2 2.0 6.0 NaN
3 NaN NaN NaN
4 4.0 8.0 NaN
'''
all_loc_res=df.dropna(axis=1,how='all')
print(all_loc_res)
'''
a b
0 0.0 4.0
1 1.0 5.0
2 2.0 6.0
3 NaN NaN
4 4.0 8.0 '''

3.5 dropna(thresh=2参数),过滤NaN时再做近一步的条件筛选

#在df中nan和None都会被自动填充为NaN
df=pd.DataFrame({'a':[np.nan,1,2,3,4],'b':[4,5,6,np.nan,np.nan],'c':[9,10,np.nan,np.nan,np.nan]},index=['index_0','index_1','index_2','index_3','index_4'])
print(df)
'''原始数据
a b c
index_0 NaN 4.0 9.0
index_1 1.0 5.0 10.0
index_2 2.0 6.0 NaN
index_3 3.0 NaN NaN
index_4 4.0 NaN NaN ''' #过滤取值,保留在行方向上至少有3个非空的项:dropna(thresh=2)
res=df.dropna(thresh=2)
print(res)
'''
a b c
index_0 NaN 4.0 9.0
index_1 1.0 5.0 10.0
index_2 2.0 6.0 NaN ''' #过滤取值,保留在列方向上至少有3个非空的项
res=df.dropna(thresh=3,axis=1)
print(res)
'''
a b
index_0 NaN 4.0
index_1 1.0 5.0
index_2 2.0 6.0
index_3 3.0 NaN
index_4 4.0 NaN '''

数据分析—NaN数据处理的更多相关文章

  1. CDA数据分析【数据处理工具SPSS】

    一.概述 SPSS[Statistical Package for the Social Science]社会科学统计软件包.SPSS统计软件在社会学.经济学.心理学.教育学等多个学科的研究工作和通信 ...

  2. kaggle数据挖掘竞赛初步--Titanic<原始数据分析&缺失值处理>

    Titanic是kaggle上的一道just for fun的题,没有奖金,但是数据整洁,拿来练手最好不过啦. 这道题给的数据是泰坦尼克号上的乘客的信息,预测乘客是否幸存.这是个二元分类的机器学习问题 ...

  3. 网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(3): 抓取amazon.com价格

    通过上一篇随笔的处理,我们已经拿到了书的书名和ISBN码.(网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(2): 抓取allitebooks.com书籍信息 ...

  4. 网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(1): 基础知识Beautiful Soup

    开始学习网络数据挖掘方面的知识,首先从Beautiful Soup入手(Beautiful Soup是一个Python库,功能是从HTML和XML中解析数据),打算以三篇博文纪录学习Beautiful ...

  5. 【VC++技术杂谈005】如何与程控仪器通过GPIB接口进行通信

    在工控测试系统中,经常需要使用到各类程控仪器,这些程控仪器通常具有GPIB.LAN.USB等硬件接口,计算机通过这些接口能够与其通信,从而实现自动测量.数据采集.数据分析和数据处理等操作.本文主要介绍 ...

  6. kaggle数据挖掘竞赛初步--Titanic<随机森林&特征重要性>

    完整代码: https://github.com/cindycindyhi/kaggle-Titanic 特征工程系列: Titanic系列之原始数据分析和数据处理 Titanic系列之数据变换 Ti ...

  7. kaggle数据挖掘竞赛初步--Titanic<派生属性&维归约>

    完整代码: https://github.com/cindycindyhi/kaggle-Titanic 特征工程系列: Titanic系列之原始数据分析和数据处理 Titanic系列之数据变换 Ti ...

  8. kaggle数据挖掘竞赛初步--Titanic<数据变换>

    完整代码: https://github.com/cindycindyhi/kaggle-Titanic 特征工程系列: Titanic系列之原始数据分析和数据处理 Titanic系列之数据变换 Ti ...

  9. .net开发笔记(十六) 对前部分文章的一些补充和总结

    补充有两个: 一个是系列(五)中讲到的事件编程(网址链接),该文提及到了事件编程的几种方式以及容易引起的一些异常,本文补充“多线程事件编程”这一块. 第二个是前三篇博客中提及到的“泵”结构在编程中的应 ...

随机推荐

  1. P1540 机器翻译

    题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先 ...

  2. redux详解

    redux介绍 学习文档:英文文档,中文文档,Github redux是什么 redux是一个独立专门用于做状态管理的JS库(不是react插件库),它可以用在react, angular, vue等 ...

  3. LeetCode94. Binary Tree Inorder Traversal

    题目 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 考点 stack ...

  4. BZOJ1053: [HAOI2007]反素数ant(爆搜)

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4163  Solved: 2485[Submit][Status][Discuss] Descript ...

  5. 洛谷P1437 [HNOI2004]敲砖块(dp)

    题目背景 无 题目描述 在一个凹槽中放置了 n 层砖块.最上面的一层有n 块砖,从上到下每层依次减少一块砖.每块砖 都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示. 14 15 4 3 23 ...

  6. hdu_4944_FSF’s game

    FSF has programmed a game. In this game, players need to divide a rectangle into several same square ...

  7. Mysql5.7创建存储过程中调用自定义函数报错Not allowed to return a result set from a function

    因为很多存储过程都会共用一段sql语句,所以我把共用的sql封装成一个自定义函数 AddCapital(); 然后通过存储过程调用,创建存储过程会报错1415,Not allowed to retur ...

  8. MongoDB模糊查询

    模糊查询简介MongoDB查询条件可以使用正则表达式,从而实现模糊查询的功能.模糊查询可以使用$regex操作符或直接使用正则表达式对象. MySQL  MongoDB select * from s ...

  9. 网络基础-交换机、路由器、OSI7层模型

    第1章 网络基础 1.1 网络的诞生 网络的诞生使命:通过各种互联网服务提升全球人类生活品质. 让人类的生活更便捷和丰富,从而促进全球人类社会的进步.并且丰富人类的精神世界和物质世界,让人类最便捷地获 ...

  10. 转:Java后端面试自我学习

    引自:https://www.cnblogs.com/JavaArchitect/p/10011253.html 最近面试java后端开发的感受:如果就以平时项目经验来面试,通过估计很难——再论面试前 ...