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]的范围内:
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,:]
字符串操作
(待补充)