目录
数据规整化:清理、转换、合并、重塑
1. 合并数据集
1.1 数据库风格的DataFrame合并
- pandas.merge() :可根据一个或多个键将不同DataFrame中的行连接起来
参数 | 说明 |
---|---|
left | 左侧df |
right | 右侧df |
how | 默认inner,还有outer,left,right |
on | 用于链接的列名或列名列表,若未指定以交集作为链接键 |
eft_on | 指定左侧作为链接键的列名或列名列表 |
right_on | 指定右侧作为链接键的列名或列名列表 |
left_index | 是否使用左侧index作为链接键 |
right_index | 是否使用右侧index作为链接键 |
sort | 根据链接键对数据排序,默认为True |
suffixes | 传入字符串值元组,分别有左右则键后缀 |
copy | 默认为True |
pd.merge(df1,df2) #未指明用哪个列进行连接,则默认将重叠列当做键
pd.merge(df1,df2,on='key') #显示指明重叠的列
pd.merge(df1,df2,on=['key1','key2']) #显示指明多个重叠列,多个键进行合并
pd.merge(df1,df2,left_on='lkey',right_on='rkey') #两个对象列名不同,进行分别指定
#索引上的合并
pd.merge(df1,df2,left_on='lkey',right_index=True) #索引上的合并
pd.merge(df1,df2,left_index=True,right_index=True) #合并双方索引
#df2(右侧df)含层次化索引,这时左侧df必须以列表的形式指明用作合并键的多个列
pd.merge(df1,df2,left_on=['key1','key2'],right_index=True)
#合并方式:inner\outer\left\right
pd.merge(df1,df2,on='key',how='outer') #多对多产生笛卡尔积行
pd.merge(df1,df2,on='key',suffixes=('_left','_right'))
1.2 索引上的合并
- pandas.merge() 也包含索引上的合并
- DataFrame.join() :按索引合并,可用于合并多个带有相同或相似索引的DataFrame对象。注意默认为左连接
df2.join(df1,how='outer') #合并双方索引
df2.join([df1,another]) #传入多个对象
1.3 轴向连接
- pandas.concat() :沿一条轴将多个对象堆叠到一起
concat函数的参数
参数 | 说明 |
---|---|
objs | 参与连接的pandas对象的列表或字典,唯一必须的参数 |
axis | 指明连接的轴向,默认为0 |
join | 连接方式,默认为outer。指明其他轴向上的索引按outer(并集)还是inner(交集)进行合并 |
join_axes | 指明用于其他n-1条轴的索引,不执行并集或交集运算 |
keys | 形成连接轴上的层次化索引,沿着axis=1进行合并,对Series:则keys就会成为DataFrame的列头;若对DataFrame,则keys成为高级列头 |
levels | 指定用作层次化索引各级别上的索引,如果设置了keys的话 |
names | 用于层次化索引的名称 |
verify_integrity | 检查结果对象新轴上的重复情况,发现则引发异常,默认Flase允许重复 |
ignore_index | 不保留链接轴上的索引,产生新索引range(total_length) |
1.4 合并重叠数据
- pandas.combine_first() :可以将重复数据编接在一起,用一个对象中的值填充另一个对象中的缺失值
#两者等价
np.where(pd.isnull(a),b,a)
a.combine_first(b)
2. 重塑和轴向旋转
2.1 旋转stack和unstack
stack:将 列 旋转为 行
unstack:将 行 旋转为 列
df = DataFrame(np.arange(6).reshape((2,3)),index=pd.Index(['Ohio','Nevada'],name='state'),columns=pd.Index(['one','two','three'],name='numbei'))
df
'''
numbei one two three
state
Ohio 0 1 2
Nevada 3 4 5
'''
df.stack()
'''
state numbei
Ohio one 0
two 1
three 2
Nevada one 3
two 4
three 5
dtype: int32
'''
df.stack().unstack() # 同df,该运算可逆
df.unstack() #默认操作最内层,同stack()
df.unstack(0) #操作最外层
df.unstack('state') #指定索引级别操作
df.unstack().stack(dropna=False) #默认为True
2.2 pivot(index=None, columns=None, values=None)
前两个参数分别作为行和列索引的列名,第三个参数是用于填充DataFrame的数据列的列名
链接–> Python pivot详解
3. 清理
3.1 移除重复数据
- DataFrame.duplicated() 返回一个bool型Series,表示各行是否重复行
- DataFrame.drop_duplicates(subset=[‘A’,‘B’],keep=‘first’,inplace=True) 清洗数据
参数 | 说明 |
---|---|
subset | 列名,将相应列对应值相同的行进行去重(默认值为subset=None表示考虑所有列) |
keep | ='first’表示保留第一次出现的重复行,是默认值。;"last"和False,分别表示保留最后一次出现的重复行和去除所有重复行 |
inplace | 为True表示直接在原来的DataFrame上删除重复项,而默认值False表示生成一个副本 |
take_last(python3.X已无该参数) | 默认为False则保留第一个,设为True则保留最后一个 |
实例:
import pandas as pd
from pandas import Series, DataFrame
data = DataFrame({'A':[1,0,2,1],
'B':[2,4,6,2],
'C':[3,2,5,3],
'D':[1,0,2,1],})
data
'''
A B C D
0 1 2 3 1
1 0 4 2 0
2 2 6 5 2
3 1 2 3 1
'''
data.duplicated()
'''
0 False
1 False
2 False
3 True
dtype: bool
'''
data.drop_duplicates(['A'])
'''参数subset=['A'],根据'A'列过滤重复项
A B C D
0 1 2 3 1
1 0 4 2 0
2 2 6 5 2
'''
data.drop_duplicates(keep=False)
'''不保留重复项
A B C D
1 0 4 2 0
2 2 6 5 2
'''
data.drop_duplicates(keep='last')
'''保留最后一次出现的重复行
A B C D
1 0 4 2 0
2 2 6 5 2
3 1 2 3 1
'''
pd.concat([data.drop_duplicates(),data.drop_duplicates(keep=False)]).drop_duplicates(keep=False)
#取DataFrame重复值
'''
A B C D
0 1 2 3 1
'''
3.2 替换值
- fillna() :填充缺失数据
- Series.replace():替换值
data.replace(-999,np.nan)
data.replace([-999,-1000],np.nan)
data.replace([-999,-1000],[np.nan,0])
data.replace({-999:np.nan,-1000:0})
4. 转换
4.1 利用函数或映射进行数据转换
使用map是一种实现元素级转换以及其他数据清理工作的便捷方式
- Series.map() : 应用元素级函数
import pandas as pd
from pandas import Series, DataFrame
data = 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]})
meat_to_animal = {
'bacon':'pig',
'pulled pork':'pig',
'pastrami':'cow',
'corned beef':'cow',
'honey ham':'pig',
'nova lox':'salmon' }
# 前一个map()为应用函数,后一个map()为字典映射
data['animal'] = data['food'].map(str.lower).map(meat_to_animal)
data
'''
food ounces animal
0 bacon 4.0 pig
1 pulled pork 3.0 pig
2 bacon 12.0 pig
3 Pastrami 6.0 cow
4 corned beef 7.5 cow
5 Bacon 8.0 pig
6 pastrami 3.0 cow
7 honey ham 5.0 pig
8 nova lox 6.0 salmon
'''
#也可以传入一个能够完成全部这些工作的函数:
data['food'].map(lambda x: meat_to_animal[x.lower()])
'''
0 pig
1 pig
2 pig
3 cow
4 cow
5 pig
6 cow
7 pig
8 salmon
Name: food, dtype: object
'''
- DataFrame.apply() : 将函数应用到各行或列所形成的的一维数组上
- DataFrame.applymap():应用元素级函数
4.2 重命名轴索引
- DataFrame.index.map():重命名索引
- DataFrame.rename():返回新的数据集,如果希望就地对索引和列标签进行赋值,传入inplace=True即可
data.index.map(str.upper) #返回新的Index
data.rename(index=str.title,columns=str.upper)
data.rename(index={'OHIO':'INDIANA'},columns={'three':'peekaboo'},inplace=True)
4.3 离散化和面元划分
- pandas.cut() :不一定均匀划分
- pandas.qcut():均匀划分
ages=[20,22,25,27,21,23,27,31,61,45,41,32]
bins=[18,25,35,60,100]
cats=pd.cut(ages,bins,right=True,labels=list('abcd')) #返回Categorical类型
cats.codes #返回所属区间的标号,始于0
cats.categories #返回所有区间
pd.value_counts(cats) #计数
cats=pd.cut(ages,4,precision=2) #最大值减最小值除4为分位,precision设置小数位数
cats=pd.qcut(ages,4,precision=2) #按4分位进行切割,4分数量接近相等
cats=pd.qcut(ages,[0,0.1,0.5,0.9,1],precision=2) #自定义分位数
4.4 检验和过滤异常值异常
利用布尔型数组
4.5 排列和随机采样
sampler=np.random.permutation(10) #产生一个排列
df.take(sampler) #指定行索排序
df.take(np.random.permutation(len(df))[:3]) #随机抽取3行数据
np.random.randint(0,10,size=100) #随机生成整数区间0-10,100个
4.6 计算指标/哑变量
pandas.get_dummies()
df=pd.DataFrame({'key':list('bbacab'),'data':[2,2,3,4,5,6]})
df.index='one,two,three,four,five,six'.split(',')
dummies=pd.get_dummies(df['key'],prefix='key') #把列数据唯一值设置为列,并加入前缀
df[['data']].join(dummies) #df[['data']]返回DataFrame;df['data']返回Series
'''
data key_a key_b key_c
one 2 0 1 0
two 2 0 1 0
three 3 1 0 0
four 4 0 0 1
five 5 1 0 0
six 6 0 1 0
'''