1、合并数据集
①、多对一合并
我们需要用到pandas中的merge函数,merge函数默认情况下合并的是两个数据集的交集(inner连接),当然还有其他的参数:
how里面有inner、outer、left、right,四个参数可以选择,分别代表:交集,并集,参与合并的左侧DataFrame,以及右侧
当列名对象相同时:
df1=pd.DataFrame({'key':['a','c','a','b','a','c','b','c'],'data1':range(8)})
df2=pd.DataFrame({'key':['a','b','d'],'data2':range(3)})
pd.merge(df1,df2,on='key')
返回
key data1 data2
0 a 0 0
1 a 2 0
2 a 4 0
3 b 3 1
4 b 6 1
当列名对象不同时:
df1=pd.DataFrame({'lkey':['a','c','a','b','a','c','b','c'],'data1':range(8)})
df2=pd.DataFrame({'rkey':['a','b','d'],'data2':range(3)})
pd.merge(df1,df2,left_on='lkey',right_on='rkey',how=‘outer’)
返回为
lkey data1 rkey data2
0 a 0.0 a 0.0
1 a 2.0 a 0.0
2 a 4.0 a 0.0
3 c 1.0 NaN NaN
4 c 5.0 NaN NaN
5 c 7.0 NaN NaN
6 b 3.0 b 1.0
7 b 6.0 b 1.0
8 NaN NaN d 2.0
②、多对多合并
df1=pd.DataFrame({'key':['b','c','b','a','b','a'],'data1':range(6)})
df2=pd.DataFrame({'key':['a','a','c','b','d'],'data2':range(5)})
pd.merge(df1,df2,on='key',how='right')
返回为
key data1 data2
0 b 0.0 3
1 b 2.0 3
2 b 4.0 3
3 c 1.0 2
4 a 3.0 0
5 a 5.0 0
6 a 3.0 1
7 a 5.0 1
8 d NaN 4
多对多合并产生的是行的笛卡尔积,即df1有2个a,df2有2个a,并集会产生4个a
当需要根据多个键进行合并时,只要传入一个列名组成的列表就可以。
在合并运算时,需要对重复列名的处理,suffixes函数可以指定附加到左右两个DataFrame对象的重复列名上的字符串
2、索引上的合并
当Dataframe中的连接键位于索引中时,可以利用merge参数的left_index=True或right_index=True来表明索引应该被用作连接键:
left1=pd.DataFrame({'key':['a','b','c','a','b','a'],'value':range(6)})
right1=pd.DataFrame({'gvalue':[2,3.5]},index=['b','c'])
pd.merge(left1,right1,left_on='key',right_index=True)
返回为
key value gvalue
1 b 1 2.0
4 b 4 2.0
2 c 2 3.5
当出现层次化索引的数据时,需要以列表的形式指明用作合并键的多个列
left=pd.DataFrame({'key1':['A','B','C','A','C','A'],
'key2':[2011,2012,21011,2012,2013,2011],
'data':np.arange(6)})
right=pd.DataFrame(np.arange(12).reshape((6,2)),
index=[['A','B','C','C','C','B'],
[2011,2012,2011,2011,2011,2012]],
columns=['event1','event2'])
pd.merge(left,right,left_on=['key1','key2'],right_index=True,how='outer')
返回为
key1 key2 data event1 event2
0 A 2011 0.0 0.0 1.0
5 A 2011 5.0 0.0 1.0
1 B 2012 1.0 2.0 3.0
1 B 2012 1.0 10.0 11.0
2 C 21011 2.0 NaN NaN
3 A 2012 3.0 NaN NaN
4 C 2013 4.0 NaN NaN
5 C 2011 NaN 4.0 5.0
5 C 2011 NaN 6.0 7.0
5 C 2011 NaN 8.0 9.0
当要合并两个数据集的索引时,只需要left_index=True,right_index=True
另外,DataFrame的join可以实现按索引合并,而且还可以合并多个具有相同或相似索引的DataFrame对象,而忽视之间有无重叠的列
left2=pd.DataFrame([[1.2],[3,4],[5,6],[7,8]],index=['a','b','c','d'],
columns=['Wang','Li'])
right2=pd.DataFrame([[9,10],[11,12],[13,14]],index=['b','c','e'],
columns=['Zhao','Liu'])
left2.join(right2,how='outer')
返回
Wang Li Zhao Liu
a 1.2 NaN NaN NaN
b 3.0 4.0 9.0 10.0
c 5.0 6.0 11.0 12.0
d 7.0 8.0 NaN NaN
e NaN NaN 13.0 14.0
还可以向join传入一组DataFrame,进行索引:
other=pd.DataFrame([[6,7],[8,9],[10,11],[12,15]],index=['a','b','c','d'],
columns=['Sun','Qian'])
left2.join([right2,other])#默认求交集
返回为
Wang Li Zhao Liu Sun Qian
a 1.2 NaN NaN NaN 6 7
b 3.0 4.0 9.0 10.0 8 9
c 5.0 6.0 11.0 12.0 10 11
d 7.0 8.0 NaN NaN 12 15
3、轴向连接
concat函数能够完成一些没有重叠索引的数据
首先对Series:
s1=pd.Series([1,2],index=['a','b'])
s2=pd.Series([5,6,4],index=['c','d','e'])
pd.concat([s1,s2])
返回
a 1
b 2
c 5
d 6
e 4
当指定axis=1时,会返回DataFrame
同时还可以指定在其他轴上边使用索引
pd.concat([s1,s2],axis=1,join_axes=[['a','c','d','e']])
返回
0 1
a 1.0 NaN
c NaN 5.0
d NaN 6.0
e NaN 4.0
当我们需要在连接轴上创建一个层次化索引的时候,可以用keys参数完成
pd.concat([s1,s2],keys=['one','two'])
返回
one a 1
b 2
two c 5
d 6
e 4
在DataFrame中,也有相似的用法:
4、合并重叠数据
在numpy中,我们用where来完成合并
在series和dataframe中,我们用combine_first来实现:
5、轴向旋转数据
在DataFrame中,可以用stack:将列旋转为行;unstack:将行旋转至列。
data=pd.DataFrame(np.arange(6).reshape((2,3)),
index=pd.Index(['A','B'],name='state'),
columns=pd.Index(['one','two','three'],name='number'))
data
返回
number one two three
state
A 0 1 2
B 3 4 5
data.stack() #得到的是series类型,不再是dataframe
返回
state number
A one 0
two 1
three 2
B one 3
two 4
three 5
同样的,可以将层次化索引的series通过unstack重排为dataframe
而且,unstack在分组里面找不到值的时候,可能会引入缺失数据,
stack默认会过滤掉缺失数据
6、数据转换 (过滤、清理)
①清除重复数据
在dataframe中,duplicated函数能够返回一个布尔型series,来表示是否有重复行;
而drop_duplicates函数则能够返回一个移除重复行的dataframe;
data = pd.DataFrame({'a1':['one']*3+['two']*4,
'a2':[1,2,2,3,3,4,4]})
data.duplicated()
返回
0 False
1 False
2 True
3 False
4 True
5 False
6 True
data.drop_duplicates
返回
a1 a2
0 one 1
1 one 2
3 two 3
5 two 4
.drop_duplicates(['a1']) 表示根据a1列过滤重复项
当我们想要保留重复项出现的后一个,则需要 指定keep=‘last’
data.drop_duplicates(['a1','a2'],keep='last')
返回
a1 a2
0 one 1
2 one 2
4 two 3
6 two 4
②、通过函数或映射完成数据转换(map函数,修改对象的数据子集)
例如,给一个dataframe通过映射添加一列:
data=pd.DataFrame({'food':['bacon','pulled pork','bacon','Pastrami',
'corned beef','Bacon','pastrami','honey ham','nova lox'],
'ounces':[3,4,6,7,5,10,5,9,12]})
#映射为食物的来源动物
meat_to_animal={'bacon':'pig','pulled pork':'pig','pastrami':'cow',
'corned beef':'cow','honey ham':'pig','nova lox':'salmon'}
data['animal'] = data['food'].map(str.lower).map(meat_to_animal)#肉类的首字母大小写不统一,转换一下
data
返回
food ounces animal
0 bacon 3 pig
1 pulled pork 4 pig
2 bacon 6 pig
3 Pastrami 7 cow
4 corned beef 5 cow
5 Bacon 10 pig
6 pastrami 5 cow
7 honey ham 9 pig
8 nova lox 12 salmon
或者通过一个匿名函数完成:注:原dataframe并未发生改变
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
③、替换值(replace函数)
fillna其实是填充缺失数据的一种特殊情况:
data = pd.Series([1,-999,2,-999,-1000,3])
-999可能是表示缺失数据的标记值,我们需要替换成pandas可以接受的NA值
data.replace(-999,np.nan)
返回
0 1.0
1 NaN
2 2.0
3 NaN
4 -1000.0
5 3.0
一次性替换多个值时:
data.replace([-999,-1000],np.nan)
返回
0 1.0
1 NaN
2 2.0
3 NaN
4 NaN
5 3.0
一一对应替换
data.replace([-999,-1000],[np.nan,0]) #传入参数也可以是字典
返回
0 1.0
1 NaN
2 2.0
3 NaN
4 0.0
5 3.0
④、重命名轴索引
用到的函数:rename,复制DataFrame并对索引和列标签进行赋值
我们来创建一个数据集的转换版
data = pd.DataFrame(np.arange(12).reshape((3,4)),
index = ['Ohio','Colorado','New York'],
columns = ['one','two','three','four'])
data.rename(index = str.title,columns = str.upper)
返回
ONE TWO THREE FOUR
Ohio 0 1 2 3
Colorado 4 5 6 7
New York 8 9 10 11
另外,rename也可以结合自典型对象实现轴标签更新:
data.rename(index = {'Ohio':'Indiana'},
columns = {'THREE':'peekaboo'})
返回
one two three four
Indiana 0 1 2 3
Colorado 4 5 6 7
New York 8 9 10 11
⑤、离散化和面元(bin)划分
在pandas中我们用cut来数据的划分:
ages = [19,30,28,60,38,45,20,25,71,37,29,54]
bins =[18,25,35,60,100]
cuts = pd.cut(ages,bins)
cuts
返回
[(18, 25], (25, 35], (25, 35], (35, 60], (35, 60], ..., (18, 25], (60, 100], (35, 60], (25, 35], (35, 60]]
Length: 12
Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
当然也可以通过计数得出每个区间个数
pd.value_counts(cuts)
返回
(35, 60] 5
(25, 35] 3
(18, 25] 3
(60, 100] 1
当right=True时,表示左开右闭,当right=False时,表示左闭右开
pd.cut(ages,[18,26,36,61,100],right=False)
返回
[[18, 26), [26, 36), [26, 36), [36, 61), [36, 61), ..., [18, 26), [61, 100), [36, 61), [26, 36), [36, 61)]
Length: 12
Categories (4, interval[int64]): [[18, 26) < [26, 36) < [36, 61) < [61, 100)]
也可以自定义面元名称:
group_names = ['Youth','YoungAdult','MiddleAged','Senior']
pd.cut(ages,bins,labels = group_names)
返回
[Youth, YoungAdult, YoungAdult, MiddleAged, MiddleAged, ..., Youth, Senior, MiddleAged, YoungAdult, MiddleAged]
Length: 12
Categories (4, object): [Youth < YoungAdult < MiddleAged < Senior]
当我们向cut传入了面元的数量,而不是面元边界,会自动通过最大最小值计算等长bin
qcut能够根据样本分位数对数据进行bin划分
data = np.random.randn(1000)
cuts = pd.qcut(data,4)
cuts
返回
[(0.664, 3.276], (0.664, 3.276], (-0.62, 0.031], (-3.3729999999999998, -0.62], (0.664, 3.276], ..., (0.664, 3.276], (0.664, 3.276], (0.664, 3.276], (-3.3729999999999998, -0.62], (-0.62, 0.031]]
Length: 1000
Categories (4, interval[float64]): [(-3.3729999999999998, -0.62] < (-0.62, 0.031] < (0.031, 0.664] < (0.664, 3.276]]
计数
pd.value_counts(cuts)
返回
(0.664, 3.276] 250
(0.031, 0.664] 250
(-0.62, 0.031] 250
(-3.3729999999999998, -0.62] 250
qcut还可以自定义分位数(0-1之间,两边都闭):
pd.qcut(data,[0,0.1,0.5,0.9,1])
返回
[(0.031, 1.216], (1.216, 3.276], (-1.193, 0.031], (-3.3729999999999998, -1.193], (0.031, 1.216], ..., (0.031, 1.216], (1.216, 3.276], (0.031, 1.216], (-3.3729999999999998, -1.193], (-1.193, 0.031]]
Length: 1000
Categories (4, interval[float64]): [(-3.3729999999999998, -1.193] < (-1.193, 0.031] < (0.031, 1.216] < (1.216, 3.276]]
⑥、检测和过滤异常值;
我们随机生成一组正态分布的数据,并对数据进行操作,假设绝对值大于3的数据都属于异常值,处理结果如下:
data = pd.DataFrame(np.random.randn(1000,4))
data.describe()
返回
0 1 2 3
count 1000.000000 1000.000000 1000.000000 1000.000000
mean 0.004248 -0.011778 -0.005787 -0.053237
std 0.976084 1.020196 1.029432 0.979127
min -3.678284 -2.695522 -3.432793 -3.393575
25% -0.681090 -0.663212 -0.745234 -0.693163
50% 0.007591 -0.003798 0.010426 -0.020312
75% 0.685027 0.646247 0.724293 0.610705
max 3.836988 3.666919 3.069855 3.051585
找出绝对值大于3的数据的所有行
data[(np.abs(data)>3).any(1)]
返回
0 1 2 3
19 -0.013692 3.279487 -0.055036 -1.515724
52 -0.827221 3.666919 -0.302976 -0.693555
114 0.611680 3.106616 -0.084244 0.682607
123 -0.621681 0.801968 -3.001182 -0.843664
133 3.836988 1.765709 3.069855 0.320651
156 0.434825 0.525397 -0.572917 -3.149598
205 -0.415999 3.185963 -0.762609 0.543016
270 -3.678284 -1.313117 0.053046 -0.670639
423 1.847537 -1.540281 -0.163496 -3.393575
505 -3.012297 -0.497900 1.715688 -1.504392
657 1.885955 3.158016 -0.972898 -1.143324
692 0.360870 0.347168 -0.460957 -3.329502
704 0.565049 1.061580 -3.059464 0.064454
760 -0.285920 -0.448922 -3.432793 -1.888091
902 -1.453302 1.406283 -0.333558 3.051585
我们可以限制数据在-3<数据<3
datas = np.sign(data)*3
data.describe()
返回
0 1 2 3
count 1000.000000 1000.000000 1000.000000 1000.000000
mean 0.004101 -0.013175 -0.005364 -0.052415
std 0.970775 1.015766 1.027695 0.976185
min -3.000000 -2.695522 -3.000000 -3.000000
25% -0.681090 -0.663212 -0.745234 -0.693163
50% 0.007591 -0.003798 0.010426 -0.020312
75% 0.685027 0.646247 0.724293 0.610705
max 3.000000 3.000000 3.000000 3.000000
np.sign()返回一个由-1和1组成的数组,用来表示原始值的符号
⑦、排列和随机采样
对DataFrame和Series的列实现随机重排序,用到np.random.permutation函数
df = pd.DataFrame(np.arange(6*4).reshape(6,4))
samper = np.random.permutation(6)
samper
返回
array([4, 1, 3, 5, 0, 2])
利用take函数使用该数组,得到
df.take(samper)
0 1 2 3
4 16 17 18 19
1 4 5 6 7
3 12 13 14 15
5 20 21 22 23
0 0 1 2 3
2 8 9 10 11
当然,也可以通过permutation随机选取子集:
df.take(np.random.permutation(len(df))[:3])
返回
0 1 2 3
0 0 1 2 3
4 16 17 18 19
3 12 13 14 15
当通过替换的方式产生样本时,可以通过np.random.randint:
get_dummies函数,产生一个k列矩阵或dataframe,其中k的意思是:一个dataframe中某一列有k个不同的值:
结合get_dummies和类似于cut等的离散化函数,能够很好完成统计应用:
values = np.random.rand(10)
bins = [0,0.2,0.4,0.6,0.8,1]
pd.get_dummies(pd.cut(values,bins))
返回
(0.0, 0.2] (0.2, 0.4] (0.4, 0.6] (0.6, 0.8] (0.8, 1.0]
0 0 0 0 1 0
1 0 0 0 0 1
2 0 0 1 0 0
3 0 0 0 1 0
4 0 1 0 0 0
5 0 1 0 0 0
6 1 0 0 0 0
7 0 0 1 0 0
8 1 0 0 0 0
9 0 0 0 0 1
7、字符串的相关操作
对字符串的操作主要有:
拆分-----split,指定分隔符
修剪空白符---strip
小写----lower
大写---upper
正则表达式(一种在文本中搜索匹配字符串模式的方法)
python里面的re模块负责对字符串应用正则表达式
import re
re.match #从开始位置开始匹配,只返回字符串的首部
re.search #搜索整个字符串,返回第一个匹配项
re.findall #搜索整个字符串,返回一个list,字符串的所有匹配项
常用功能函数: