数据分析—NaN数据处理
目的
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数据处理的更多相关文章
- CDA数据分析【数据处理工具SPSS】
一.概述 SPSS[Statistical Package for the Social Science]社会科学统计软件包.SPSS统计软件在社会学.经济学.心理学.教育学等多个学科的研究工作和通信 ...
- kaggle数据挖掘竞赛初步--Titanic<原始数据分析&缺失值处理>
Titanic是kaggle上的一道just for fun的题,没有奖金,但是数据整洁,拿来练手最好不过啦. 这道题给的数据是泰坦尼克号上的乘客的信息,预测乘客是否幸存.这是个二元分类的机器学习问题 ...
- 网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(3): 抓取amazon.com价格
通过上一篇随笔的处理,我们已经拿到了书的书名和ISBN码.(网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(2): 抓取allitebooks.com书籍信息 ...
- 网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(1): 基础知识Beautiful Soup
开始学习网络数据挖掘方面的知识,首先从Beautiful Soup入手(Beautiful Soup是一个Python库,功能是从HTML和XML中解析数据),打算以三篇博文纪录学习Beautiful ...
- 【VC++技术杂谈005】如何与程控仪器通过GPIB接口进行通信
在工控测试系统中,经常需要使用到各类程控仪器,这些程控仪器通常具有GPIB.LAN.USB等硬件接口,计算机通过这些接口能够与其通信,从而实现自动测量.数据采集.数据分析和数据处理等操作.本文主要介绍 ...
- kaggle数据挖掘竞赛初步--Titanic<随机森林&特征重要性>
完整代码: https://github.com/cindycindyhi/kaggle-Titanic 特征工程系列: Titanic系列之原始数据分析和数据处理 Titanic系列之数据变换 Ti ...
- kaggle数据挖掘竞赛初步--Titanic<派生属性&维归约>
完整代码: https://github.com/cindycindyhi/kaggle-Titanic 特征工程系列: Titanic系列之原始数据分析和数据处理 Titanic系列之数据变换 Ti ...
- kaggle数据挖掘竞赛初步--Titanic<数据变换>
完整代码: https://github.com/cindycindyhi/kaggle-Titanic 特征工程系列: Titanic系列之原始数据分析和数据处理 Titanic系列之数据变换 Ti ...
- .net开发笔记(十六) 对前部分文章的一些补充和总结
补充有两个: 一个是系列(五)中讲到的事件编程(网址链接),该文提及到了事件编程的几种方式以及容易引起的一些异常,本文补充“多线程事件编程”这一块. 第二个是前三篇博客中提及到的“泵”结构在编程中的应 ...
随机推荐
- 用蒙特卡洛方法计算派-python和R语言
用蒙特卡洛方法算pi-基于python和R语言 最近follow了MOOC上一门python课,开始学Python.同时,买来了概率论与数理统计,准备自学一下统计.(因为被鄙视过不是统计专业却想搞数据 ...
- 堆优化dijkstra
单源最短路径 题目链接:https://www.luogu.org/problemnew/show/P4779 直到做了这个题才发现我之前写的堆优化dijkstra一直是错的.. 这个堆优化其实很容易 ...
- Webpack4 学习笔记三 ES6+语法降级为ES5
前言 此内容是个人学习笔记,以便日后翻阅.非教程,如有错误还请指出 Webpack 将es6.es7语法降级为es5 需要通过 babel JavaScript编译器. 安装: npm i babel ...
- 没有CTO的Netflix有哪些值得我们学习的工程文化?
作者介绍: 杨波,拍拍贷基础框架研发总监.具有超过 10 年的互联网分布式系统研发和架构经验,曾先后就职于:eBay 中国研发中心(eBay CDC),任资深研发工程师,参与亿贝开放 API 平台研发 ...
- MySQL为何不建议使用null列
Preface Null is a special constraint of columns.The columns in table will be added null cons ...
- django+xadmin在线教育平台(十二)
6-4 用form实现登录-1 上面我们的用户登录的方法是基于函数来做的.本节我们做一个基于类方法的版本. 要求对类的继承有了解. 基础教程中基本上都是基于函数来做的,其实更推荐基于类来做.基于类可以 ...
- 浅谈PHP中的数组和JS中的数组
最近在做前后端对接的时候,遇到一个问题,前端要求返回的数据格式是左边的,但是我通过json_encode返回到的数据格式是右边的 注意:数据格式从"[]"(数组)变成了&quo ...
- gdb-pada调试实例
先编写个简单的hello的程序 hello.c (ps:有没有头文件行不行,试试不就知道了) int main(){ printf("hello!\n"); int m,n; in ...
- kali linux渗透系统的安装
Kali 安装详细步骤 实验环境 Windows:Windows 10 企业版 VMware:VMware Workstation 12 Pro Kali:kali-linux-2016.2-am ...
- 生产者消费者-Java代码实现
import java.util.LinkedList; class Storage{ private static final int MAX = 100; LinkedList<Object ...