利用Python进行数据分析——数据清洗与准备

import numpy as np
import pandas as pd

处理缺失数据

丢弃含缺失值的行列

默认的dropna()方法会丢弃所有含缺失值的行:

frame=pd.DataFrame([[1,6.5,None],[1,None,None],
                   [None,None,None],[6.5,3,None]])
cleaned=frame.dropna()
frame

cleaned

可以指定丢弃缺失值的方式,当只有一行或一列全部是缺失值时才进行丢弃:

data_1=frame.dropna(how='all',axis=0)        #丢弃全为空值的行
data_1

data_2=frame.dropna(how='all',axis=1)        #丢弃全为空值的列
data_2

还可以指定丢弃数据的上限值,pandas会优先丢弃拥有更多缺失值的行:

data_3=frame.dropna(thresh=2)
data_3

填充缺失值

可以使用fillna()方法来填充缺失值:

frame.fillna(0)

可以给fillna()传递一个字典来显示说明对某一列填充的值:

frame.fillna({
    0:0,
    1:1,
    2:2
})

使用前面的值来对缺失值进行插值:

frame.fillna(method='ffill')

使用统计数字对缺失值进行填充:
···
frame.iloc[:,0].fillna(frame.iloc[:,0].median()) #中位数填充
···

frame.iloc[:,1].fillna(frame.iloc[:,1].mean())        #均值填充

数据转换

移除重复数据

frame=pd.DataFrame({
    'C1':['one','two']*2+['two'],
    'C2':[1,1,2,3,3]
})
frame

frame.drop_duplicates()        #丢弃重复的最后一行

也可指定列丢弃重复的行:

frame.drop_duplicates(['C1'])

映射

可以使用map()方法根据已有的数据按照指定的映射关系生成新数据:

frame=pd.DataFrame({
    'food':['bacon','pulled pork','bacon','Pastrami','corned beef','Bacon','pastrami','honey ham','nova lox'],
    'ounces':[4,3,12,6,7.5,8,3,5,6]
})
frame

指定映射关系:

meat2animal={
    'bacon':'pig',
    'pulled pork':'pig',
    'pastrami':'cow',
    'corned beef':'cow',
    'honey ham':'pig',
    'nova lox':'salmon'
}

因为原DF中有大小写,所以应用map()方法之前需要转换成小写:

frame['animal']=frame.loc[:,'food'].str.lower().map(meat2animal)
frame

值的替换

假设在数据中存在非常明显的异常值,则这些数据可能是被填充过的。比如下面的数据,其中的-999很可能是代表着缺失值,在数据还原的时候可以将其替换成缺失值。

obj=pd.Series([1,-999,2,3,4,-999])
obj.replace([-999],[None])

也可以用字典的形式进行替换:

replace_map={
    -999:None
}
obj.replace(replace_map)

行列标签的更改

同数据一样,行列标签也可以用函数或映射来更改。

frame=pd.DataFrame(
    np.arange(12).reshape((3,4)),
    index=['Ohio','Colorado','New York'],
    columns=['one','two','three','four']
)
frame

index_trans=lambda x:x[:4].upper()
frame.index.map(index_trans)

Index([‘OHIO’, ‘COLO’, ‘NEW ‘], dtype=’object’)

对于单个或少数行列标签的修改,使用rename()方法更方便:

frame.rename(
    index={'Ohio':'Indiana'},
    columns={'three':'peekaboo'},
    inplace=True
)
frame

数据的离散化

ages=[20,22,25,27,21,23,37,31,61,45,41,32]
bins=[18,25,35,60,100]        #五个分割点将数据分成4个区间
group_names=['Youth','YoungAdult','MiddleAged','Senior']
cats=pd.cut(ages,bins,labels=group_names)
cats.value_counts()

Youth 5
YoungAdult 3
MiddleAged 3
Senior 1
dtype: int64

还可以直接指定分割区间数:

data=np.random.randn(20)
cats=pd.cut(data,4)        #将区间平均分成4个子区间
cats.value_counts()

(-1.679, -0.908] 3
(-0.908, -0.14] 5
(-0.14, 0.628] 7
(0.628, 1.396] 5
dtype: int64

cut()方法是按区间的取值范围将区间划分成子区间,qcut()方法是按照样本的分位数来进行划分,qcut()方法保证每个子区间都拥有同样数量的样本:

data=np.random.randn(100)
cats=pd.qcut(data,[0,0.1,0.5,0.9,1])        #指定百分位数
cats.value_counts()

(-2.492, -1.21] 10
(-1.21, 0.0562] 40
(0.0562, 1.231] 40
(1.231, 2.355] 10
dtype: int64

data=np.random.randn(100)
cats=pd.qcut(data,4)        #指定子区间数
cats.value_counts()

(-1.9609999999999999, -0.424] 25
(-0.424, -0.012] 25
(-0.012, 0.581] 25
(0.581, 2.144] 25
dtype: int64

异常值

考虑一个服从标准正态分布的数据集,根据 3 σ 原则,可以将绝对值大于3的值视为异常值,将数据集中的值截断到[-3,3]的范围内:

data=pd.DataFrame(np.random.randn(1000,3))
data.describe()

将异常值截断为-3或3:

data[(np.abs(data)>3)]=np.sign(data)*3
data.describe()

数据重排与随机采样

在机器学习项目中,数据重排常用于打乱数据集,然后划分训练集与测试集;而随机采样通常用于生成小批量的训练数据集。

frame=pd.DataFrame(np.arange(20).reshape((5,4)))
re_order=np.random.permutation(frame.shape[0])

training_set=frame.iloc[re_order[:3],:]
test_set=frame.iloc[re_order[3:],:]
mini_batch=training_set.sample(1,replace=True)
training_set

test_set

mini_batch

哑变量

在机器学习项目中,有时需要对变量进行独热编码或生成哑变量以增加系统的非线性。

frame=pd.DataFrame({
    'key':['b','b','a','c']
})
dummies=pd.get_dummies(frame.loc[:,'key'],prefix='key')
dummies

对于某些数据可能同时具有多个同类属性,如电影数据,一部电影可能同时属于爱情片和动作片是可能的。这种数据的转换稍稍麻烦一点:

movies=pd.read_table('datasets/movielens/movies.dat',sep='::',header=None,names=['id','title','genre'],engine='python')
movies.sample(3)

首先将所有的电影类型全部抽取出来:

genres=[]
for genre in movies.iloc[:,2]:
    genres.extend(genre.split('|'))
genres=pd.unique(genres)
genres

再生成一个对应形状的空矩阵:

dummies=pd.DataFrame(np.zeros((movies.shape[0],len(genres))),columns=genres,dtype=int)

利用原数据的信息,将dummies数据集中相应的位置置1:

for row_index,genre in enumerate(movies.iloc[:,2]):
    col_index=dummies.columns.get_indexer(genre.split('|'))
    dummies.iloc[row_index,col_index]=1

将哑变量数据加入到原数据集中:

new_data=movies.join(dummies)
new_data.iloc[0,:]

字符串操作

(待补充)

猜你喜欢

转载自blog.csdn.net/qq_31823267/article/details/79919612