利用Python进行数据分析(五):数据清洗和准备
一、处理缺失数据
pandas对象的所有描述性统计默认都不包括缺失数据。
1、检测缺失数据
比如新建一个Series,用isnull函数检测是否为缺失值,对于数值数据,pandas使用浮点值NaN(Not a Number)表示缺失数据。
import numpy as np
import pandas as pd
string_data = pd.Series(['aar', 'art', np.nan, 'avo'])
string_data
0 aar
1 art
2 NaN
3 avo
dtype: object
string_data.isnull()
0 False
1 False
2 True
3 False
dtype: bool
当进行数据清洗以进行分析时,最好直接对缺失数据进行分析,以判断数据采集的问题或缺失数据可能导致的偏差。
Python内置的None值在对象数组中也可以作为NA:
string_data[0]=None
string_data
0 None
1 art
2 NaN
3 avo
dtype: object
string_data.isnull()
0 True
1 False
2 True
3 False
dtype: bool
处理缺失数据的函数
2、过滤缺失数据
Series
对于一个Series,dropna返回一个仅含非空数据和索引值的Series:
string_data.dropna()
1 art
3 avo
dtype: object
from numpy import nan as na
data = pd.Series([1,na,3.5,na,7])
data
0 1.0
1 NaN
2 3.5
3 NaN
4 7.0
dtype: float64
data.dropna()
0 1.0
2 3.5
4 7.0
dtype: float64
data[data.notnull()]
0 1.0
2 3.5
4 7.0
dtype: float64
data.dropna()等价于data[data.notnull()]
DataFrame
而对于DataFrame对象,事情就有点复杂了。你可能希望丢弃全NA或含有NA的行或列。dropna默认丢弃任何含有缺失值的行:
data1 = pd.DataFrame([[1,2,3],[1,na,na],[na,na,na],[na,6.5,3]])
data1
0 1 2
0 1.0 2.0 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
cleaned = data1.dropna()
cleaned
0 1 2
0 1.0 2.0 3.0
传入how=’all’将只丢弃全为NA的那些行:
data1.dropna(how='all')
0 1 2
0 1.0 2.0 3.0
1 1.0 NaN NaN
3 NaN 6.5 3.0
用这种方式丢弃列,只需传入axis=1即可:
data1.dropna(axis=1,how='all')
0 1 2
0 1.0 2.0 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
时间序列
假设你只想留下一部分观测数据,可以用thresh参数实现此目的:
df = pd.DataFrame(np.random.randn(7,3))
df.iloc[:4,1]=na
df
0 1 2
0 -0.656451 NaN -0.961644
1 0.139871 NaN -0.390374
2 0.264801 NaN -0.399654
3 -0.242247 NaN 0.871069
4 0.975986 -0.763189 1.567743
5 -1.128100 -0.355459 -0.050403
6 -0.614838 0.359948 0.173833
df.iloc[:2,2]=na
df
0 1 2
0 -0.656451 NaN NaN
1 0.139871 NaN NaN
2 0.264801 NaN -0.399654
3 -0.242247 NaN 0.871069
4 0.975986 -0.763189 1.567743
5 -1.128100 -0.355459 -0.050403
6 -0.614838 0.359948 0.173833
df.dropna()
0 1 2
4 0.975986 -0.763189 1.567743
5 -1.128100 -0.355459 -0.050403
6 -0.614838 0.359948 0.173833
df.dropna(thresh=2)
0 1 2
2 0.264801 NaN -0.399654
3 -0.242247 NaN 0.871069
4 0.975986 -0.763189 1.567743
5 -1.128100 -0.355459 -0.050403
6 -0.614838 0.359948 0.173833
填充缺失数据
df.fillna(0)
0 1 2
0 -0.656451 0.000000 0.000000
1 0.139871 0.000000 0.000000
2 0.264801 0.000000 -0.399654
3 -0.242247 0.000000 0.871069
4 0.975986 -0.763189 1.567743
5 -1.128100 -0.355459 -0.050403
6 -0.614838 0.359948 0.173833
若是通过一个字典调用fillna,就可以实现对不同的列填充不同的值:
df.fillna({1:0.5,2:2.5})
0 1 2
0 -0.656451 0.500000 2.500000
1 0.139871 0.500000 2.500000
2 0.264801 0.500000 -0.399654
3 -0.242247 0.500000 0.871069
4 0.975986 -0.763189 1.567743
5 -1.128100 -0.355459 -0.050403
6 -0.614838 0.359948 0.173833
fillna默认会返回新对象,但也可以对现有对象进行就地修改:
_=df.fillna(0,inplace=True)
df
0 1 2
0 -0.656451 0.000000 0.000000
1 0.139871 0.000000 0.000000
2 0.264801 0.000000 -0.399654
3 -0.242247 0.000000 0.871069
4 0.975986 -0.763189 1.567743
5 -1.128100 -0.355459 -0.050403
6 -0.614838 0.359948 0.173833
对reindexing有效的那些插值方法也可用于fillna:
ffill向前填充,向下填充
bfill向后填充,向上填充
df=pd.DataFrame(np.random.randn(6,3))
df
0 1 2
0 2.189955 -1.769679 -0.844384
1 -2.173418 0.289250 -2.216570
2 -0.414842 -0.115741 0.780312
3 0.244778 1.031849 0.604387
4 1.240619 -1.017771 -0.074853
5 -0.105774 -0.821069 0.118463
df.iloc[:2,1]=na
df
0 1 2
0 2.189955 NaN -0.844384
1 -2.173418 NaN -2.216570
2 -0.414842 -0.115741 0.780312
3 0.244778 1.031849 0.604387
4 1.240619 -1.017771 -0.074853
5 -0.105774 -0.821069 0.118463
df.iloc[:4,2]=na
df
0 1 2
0 2.189955 NaN NaN
1 -2.173418 NaN NaN
2 -0.414842 -0.115741 NaN
3 0.244778 1.031849 NaN
4 1.240619 -1.017771 -0.074853
5 -0.105774 -0.821069 0.118463
df.fillna(method='bfill')
0 1 2
0 2.189955 -0.115741 -0.074853
1 -2.173418 -0.115741 -0.074853
2 -0.414842 -0.115741 -0.074853
3 0.244778 1.031849 -0.074853
4 1.240619 -1.017771 -0.074853
5 -0.105774 -0.821069 0.118463
比如说,你可以传入Series的平均值或中位数:
s=pd.Series([1,na,4,na,5,8])
s.fillna(s.mean())
0 1.0
1 4.5
2 4.0
3 4.5
4 5.0
5 8.0
dtype: float64
fillna()的参数
二、数据转换
1、移除重复数据
data = pd.DataFrame({'k1':['one','two'] * 3 + ['two'],'k2':[1,1,2,3,3,4,4]})
data
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
5 two 4
6 two 4
DataFrame的duplicated方法返回一个布尔型Series,表示各行是否是重复行:
data.duplicated()
0 False
1 False
2 False
3 False
4 False
5 False
6 True
dtype: bool
还有一个与此相关的drop_duplicates方法,它会返回一个DataFrame,重复的数组会标为False:
data.drop_duplicates()
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
5 two 4
这两个方法默认会判断全部列,你也可以指定部分列进行重复项判断。假设我们还有一列值,且只希望根据k1列过滤重复项:
data['v1'] = range(7)
data
k1 k2 v1
0 one 1 0
1 two 1 1
2 one 2 2
3 two 3 3
4 one 3 4
5 two 4 5
6 two 4 6
data.drop_duplicates(['k1'])
k1 k2 v1
0 one 1 0
1 two 1 1
duplicated和drop_duplicates默认保留的是第一个出现的值组合。传入keep=’last’则保留最后一个:
data.drop_duplicates(['k1'],keep='last')
k1 k2 v1
4 one 3 4
6 two 4 6
2、利用函数或映射进行数据转换
对于许多数据集,你可能希望根据数组、Series或DataFrame列中的值来实现转换工作。我们来看看下面这组有关肉类的数据:
data = pd.DataFrame({'food':['s1','s2','s3','s4','s5','s6'],'price':range(6)})
data
food price
0 s1 0
1 s2 1
2 s3 2
3 s4 3
4 s5 4
5 s6 5
假设你想要添加一列表示该肉类食物来源的动物类型。我们先编写一个不同肉类到动物的映射:
如果有的大写,有的小写,用Series的str.lower方法,将各个值转换为小写。
data['animal'] = data['food'].map(foodt)
data
food price animal
0 s1 0 cow
1 s2 1 pig
2 s3 2 salmon
3 s4 3 cow
4 s5 4 pig
5 s6 5 salmon
map是series的函数
3、替换值
利用fillna方法填充缺失数据可以看做值替换的一种特殊情况。前面已经看到,map可用于修改对象的数据子集,而replace则提供了一种实现该功能的更简单、更灵活的方式。我们来看看下面这个Series:
data = pd.Series([1,-999,2,-999,3,-1000])
data
0 1
1 -999
2 2
3 -999
4 3
5 -1000
999这个值可能是一个表示缺失数据的标记值。要将其替换为pandas能够理解的NA值,我们可以利用replace来产生一个新的Series(除非传入inplace=True):
data.replace(-999,np.nan)
0 1.0
1 NaN
2 2.0
3 NaN
4 3.0
5 -1000.0
dtype: float64
如果你希望一次性替换多个值,可以传入一个由待替换值组成的列表以及一个替换值:
data.replace([-999,1,-1000],np.nan)
0 NaN
1 NaN
2 2.0
3 NaN
4 3.0
5 NaN
dtype: float64
要让每个值有不同的替换值,可以传递一个替换列表:
data.replace([-999,-1000],[np.nan,0])
0 1.0
1 NaN
2 2.0
3 NaN
4 3.0
5 0.0
dtype: float64
传入的参数也可以是字典:
data.replace({-999:np.nan,-1000:0})
0 1.0
1 NaN
2 2.0
3 NaN
4 3.0
5 0.0
dtype: float64
4、重命名轴索引
跟Series中的值一样,轴标签也可以通过函数或映射进行转换,从而得到一个新的不同标签的对象。轴还可以被就地修改,而无需新建一个数据结构。
Original: https://blog.csdn.net/catchmeifyoucOol/article/details/121479677
Author: catchcatpath
Title: 利用Python进行数据分析(五):数据清洗和准备
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/754582/
转载文章受原作者版权保护。转载请注明原作者出处!