目的

  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. 使用cmd命令创建maven(web)项目+项目转换成IDEA项目+项目打包+Jetty运行Web项目

    3条件:配置好环境 配置环境教程:https://www.cnblogs.com/weibanggang/p/9623705.html 第一步:查看版本信息,在cmd输入mvn –version,如果 ...

  2. System.Web.UI.HtmlControls

    用来创建一个标签.HtmlContainerControl 一般用此类来新建标签. 可能我们熟悉System.Web.UI.WebControls;空间.System.Web.UI.WebContro ...

  3. css中hover设置边框后div中内容后移解决方法

    <style> .demo{width:1200px;height:400px;background:#fff;} .demo:hover{border:1px solid #cecece ...

  4. java基础 数组 Set Map 集合综合应用 生成带0的随机字符串 "00000001" 水果商品号问题

    package com.swift.test01; /*有四种水果(苹果,香蕉,西瓜,橘子) 1.给每种水果设定一个商品号,商品号是8个0-9的随机数,商品号码不能重复, 最小值 "0000 ...

  5. C++声明之CV限定符

    目录 1.const 1.1 const obj 如果调用 non-const member fun会编译出错 经典错误 1.2 例子:STD里的操作符重载 1.3 例子:<cpp primer ...

  6. 手机丢了怎么办?MZ给你来支招

    1致电运营商挂失手机 2致电银行冻结手机网银 3手机绑定支付宝的拨95188挂失 4微信用户登录110.qq.com冻结账号 5修改微博.微信.QQ等密码 6到手机运营商处补手机卡. 一定要记住啊!手 ...

  7. select值改变

    改变select的值,然后执行一个方法.可以用chang: $("#select").change(function(){ //要执行的内容 });

  8. gcc常用语法

    1. gcc -E source_file.c-E,只执行到预编译.直接输出预编译结果. 2. gcc -S source_file.c -S,只执行到源代码到汇编代码的转换,输出汇编代码. 3. g ...

  9. 2016 ACM-ICPC Asia China-Final D 二分

    题意:一共有N个冰淇淋球,做一个冰淇淋需要K个球,并且由于稳定性,这K个球还必须满足上下相邻的下面比上面大至少两倍.先给出N个球的质量,问最多能做出多少个冰淇淋? 思路:二分答案并对其检验. 检验标准 ...

  10. 读懂CCS链接命令文件(.cmd)

    链接器的核心工作就是符号表解析和重定位,链接命令文件则使得编程者可以给链接器提供必要的指导和辅助信息.多数时候,由于集成开发环境的存在,开发者无需了解链接命令文件的编写,使用默认配置即可.但若需要对计 ...