5.数据清洗与整理
1.数据清洗
- (1)处理缺失值
- 1.侦查缺失值
- df.isnull()
- True的为缺失值
- df.notnull()
- False为缺失值
- df.info
- 查看dataframe字段信息
from pandas import Series,DataFrame
import pandas as pd
import numpy as np
%matplotlib inline
df1 = DataFrame([[3,5,3],[1,6,np.nan],
['lili',np.nan,'pop'],[np.nan,'a','b']])
df1
df1.isnull() #True的为缺失值
df1.notnull() #False为缺失值
df1.isnull().sum() #通过求和可以获取每列的缺失值数量
df1.isnull().sum().sum() # 再通过求和可以获取整个DataFrame的缺失值数量
- 2.删除缺失值
- df.dropna(how='all', axis=1)
df2 = DataFrame(np.arange(12).reshape(3,4))
df2
# df2.ix[2,:] = np.nan # ix混合操作操作已经无效
df.iloc[2, :] = np.nan
df2[3] = np.nan # 列
df2
df2.dropna(how='all') # 删除 行全为NaN 的缺失值
df2.dropna(how='all',axis=1) # 删除 列全为NaN 的缺失值
- 3.填充缺失值
- df.fillna()
- 将缺失值替换为常数值,返回的新对象,不会对原数据进行修改,但是通过inplace就地进行修改
- 在fillna中传入字典结构数据,可以针对不同列填充不同的值
- 利用method参数实现ffill、bfill填充(参考前面的数据填充)
df2.fillna(0) # 所有的NaN替换为0
df2.fillna({1:6,3:0}) # ’1‘列替换为6,’3‘列替换为0
# 以上操作都不会对原先值进行修改,通过inplace参数可以实现修改
df2.fillna({1:6,3:0},inplace=True)
df2
# 参考前面的数据填充
df2.fillna(method='ffill')
# 均值填充
df2[0] = df2[0].fillna(df2[0].mean())
df2
- 通过df.fillna?进行帮助查询
-(2)移除重复值
- duplicated()
- 判断各行是否有重复数据
# 创建数据
data = {
'name':['张三', '李四', '张三', '小明'],
'sex':['female', 'male', 'female', 'male'],
'year':[2001, 2002, 2001, 2002],
'city':['北京', '上海', '北京', '北京']
}
df1 = DataFrame(data)
df1
# 判断各行是否有重复的数据,返回布尔类型
df1.duplicated()
- drop_duplicates()
- 1.默认是全匹配才删除
- 2.指定部分列匹配删除
# 创建数据
data = {
'name':['张三', '李四', '张三', '小明'],
'sex':['female', 'male', 'female', 'male'],
'year':[2001, 2002, 2001, 2002],
'city':['北京', '上海', '北京', '北京']
}
df1 = DataFrame(data)
df1
# 默认当每个字段都是相同时才会判断是否为重复项
df1.drop_duplicates() # 删除重复数据
# 指定部分列作为判断重复项的依据
df1.drop_duplicates(['sex','year'])
# 以上保留的数据都是第一次出现的组合
# 通过keep参数可以保留最后一个出现的组合
df1.drop_duplicates(['sex','year'],keep='last')
- (3)替换值
- replace()
- 单值替换
- 多值替换
- 列表实现
- 字典实现
# 创建数据
data = {
'name':['张三', '李四', '王五', '小明'],
'sex':['female', 'male', '', 'male'],
'year':[2001, 2003, 2001, 2002],
'city':['北京', '上海', '', '北京']
}
df1 = DataFrame(data)
df1
# 替换数据,空格替换为"不详"
df1.replace('','不详')
# 多值替换,空格替换为“不详”,“2001”替换为“2002”
df1.replace(['',2001],['不详',2002]) # 利用列表实现
df1.replace({'':'不详',2001:2002}) # 利用字典实现
- (4)利用函数或者映射进行数据转换
# 创建数据
data = {
'name':['张三', '李四', '王五', '小明'],
'math':[79, 52, 63, 92]
}
df2 = DataFrame(data)
df2
# 定义函数
def f(x):
if x >= 90:
return '优秀'
elif 70<=x<90:
return '良好'
elif 60<=x<70:
return '合格'
else:
return '不合格'
# 调用函数
df2['class'] = df2['math'].map(f) # map针对Series中的每一个元素
df2
del df2['class']
df2
# apply针对DataFrame的 行和列
df2['class'] = df2['math'].apply(f)
df2
- (5)检测异常值
- 根据经验 和 可视化技术 进行判断
- (6)虚拟变量,详见P103
2.数据合并和重塑
- 1.合并
(1)merge合并
- 1.left、right
- 参与合并的左(右)侧DataFrame
- 2.how
- 连接方法:inner、left、right、outer
- 3.on
- 指定连接的列名
- 4.left_on,right_on
- 左(右)侧DataFrame中用于连接键的列
- 5.left_index,right_index
- 左(右)侧DataFrame的行索引作为连接键
- 6.sort
- 合并后会对数据排序,默认为Ture
- 7.suffixes
- 修改重复名
通过一个或者多个键(DataFrame的列)将两个DataFrame按行合并起来
# 默认为内连接(inner),返回交集
# 创建数据
price = DataFrame({
'fruit':['apple','banana','orange'],
'price':[23,32,45]
})
amount = DataFrame({
'fruit':['apple','banana','apple','apple','banana','pear'],
'amount':[5,3,6,3,5,7]
})
# 列中不是共同的元素将被抛弃
pd.merge(amount, price) #内连接,交集
# 利用参数on指定列名连接
pd.merge(amount,price,on='fruit')
pd.merge(amount,price,left_on='fruit',right_on='fruit')
# 通过how参数选择连接方法:左连接(left)、右连接(right)、外连接(outer)
pd.merge(amount,price,how='left')
pd.merge(amount,price,how='right')
pd.merge(amount,price,how='outer')
left = DataFrame({
'key1':['one','one','two'],
'key2':['a','b','a'],
'val1':[2,3,4]
})
right = DataFrame({
'key1':['one','one','two','two'],
'key2':['a','a','a','b'],
'val2':[5,6,7,8]
})
# 重复列名的修改,suffixes用于处理该问题
pd.merge(left,right,on='key1',suffixes=('_left','_right'))
# 有时候连接的键位于DataFrame的 行索引 上,可以通过传入left_index =Ture 或者right_index=Ture指定将索引作为连接键来使用
pd.merge(left2,right2,left_on='key',right_index=True)
- (2)concat连接,详见P110页
- 没有相同索引的Series,使用concat连接,axis=0/1
- 只有内连接和外连接,join=’inner/outer‘
- join_axes指定使用的索引顺序
- (3)combine_first合并
- 解决的问题:需要合并的两个DataFrame存在重复的索引
- 2.重塑
- stack()
- 用于将DataFrame的列“旋转”为行
- unstack()
- 用于将DataFrame的行“旋转”为列
df = DataFrame(np.arange(9).reshape(3,3),
index = ['a','b','c'],
columns=['one','two','three'])
df.index.name = 'alph'
df.columns.name = 'number'
df
result = df.stack()
result
result.unstack()
3.字符串处理
- (1)字符串方法
- 例子:将数据分为两列
# 创建数据
data = {
'data':['张三|男', '李四|女', '王五|女', '小明|男'],
}
df = DataFrame(data)
df
# apply函数调用,实现数据分开
result = df['data'].apply(lambda x:Series(x.split('|')))
result
# 字符串方式实现
new_df = df['data'].str.split('|')
new_df
df['name'] = new_df.str[0]
df['sex'] = new_df.str[1]
df
- (2)正则表达式