数据合并、拼接

Pandas包的merge、join、concat方法可以完成数据的合并和拼接,merge方法主要基于两个dataframe的共同列进行合并,join方法主要基于两个dataframe的索引进行合并,concat方法是对series或dataframe进行行拼接或列拼接。

一、数据合并

1、merge

pandas的merge方法是基于共同列,将两个dataframe连接起来。merge方法的主要参数:

	pd.merge(left,right,how="inner", on=None,left_on = None,right_on = None,left_index = False, right_index = False, shuffle=("_x","_y"),copy=True,indicator=False,validate =None)
  • left/right:左/右位置的dataframe。
  • how:数据合并的方式。left:基于左dataframe列的数据合并;right:基于右dataframe列的数据合并
  • outer:基于列的数据外合并(取并集);inner:基于列的数据内合并(取交集);默认为’inner’。
  • on:用来合并的列名,这个参数需要保证两个dataframe有相同的列名。
  • left_on/right_on:左/右dataframe合并的列名,也可为索引,数组和列表。
  • left_index/right_index:是否以index作为数据合并的列名,True表示是。
  • sort:根据dataframe合并的keys排序,默认是。
  • suffixes:若有相同列且该列没有作为合并的列,可通过suffixes设置该列的后缀名,一般为元组和列表类型;如果列有重名,自动添加后缀,默认是("_x","_y")。
    merges通过设置how参数选择两个dataframe的连接方式,有内连接,外连接,左连接,右连接。

(1) 内连接 inner

how=‘inner’,dataframe的链接方式为内连接,我们可以理解基于共同列的交集进行连接,参数on设置连接的共有列名;
左右的表的数据都有,才会出现在结果里

# 单列的内连接
#定义数据
   df1 = pd.DataFrame({'alpha':['A','B','B','C','D','E'],'col1':[1,1,2,3,3,1],
               'col2':['low','medium','medium','high','low','high']})
#定义df2
   df2 = pd.DataFrame({'alpha':['A','A','B','F'],'pazham':['apple','orange','pine','pear'],
               'kilo':['high','low','high','medium'],'price':np.array([5,6,5,7])})
   print(df1)
   print(df2)
打印的数据为:
   			  alpha  col1    col2                         alpha  pazham    kilo  price
   			0     A     1     low                    0      A      apple     high    5
   			1     B     1  medium                    1      A      orange    low     6
   			2     B     2  medium                    2      B       pine     high    5   
   			3     C     3    high                    3      F       pear    medium   7
   			4     D     3     low                                           
   			5     E     1    high                                           
 #基于共同列alpha的内连接
   df3 = pd.merge(df1,df2,how='inner',on='alpha')
   print(df3)
#输出结果:取共同列alpha值的交集进行连接
   			   alpha  col1    col2  pazham  kilo  price
   			0     A     1     low   apple  high      5
   			1     A     1     low  orange   low      6
   			2     B     1  medium    pine  high      5
   			3     B     2  medium    pine  high      5

(2) 外连接

how=‘outer’,dataframe的链接方式为外连接,我们可以理解基于共同列的并集进行连接,参数on设置连接的共有列名;
左右两表的所有数据都会出现在结果里面,无法匹配则为NaN

	df3 = pd.merge(df1,df2,how='outer',on='alpha')
	print(df3)
  # 输出结果:若两个dataframe间除了on设置的连接列外并无相同列,则该列的值置为NaN。
				   alpha  col1    col2  pazham    kilo  price
				0     A   1.0     low   apple    high    5.0
				1     A   1.0     low  orange     low    6.0
				2     B   1.0  medium    pine    high    5.0
				3     B   2.0  medium    pine    high    5.0
				4     C   3.0    high     NaN     NaN    NaN
				5     D   3.0     low     NaN     NaN    NaN
				6     E   1.0    high     NaN     NaN    NaN
				7     F   NaN     NaN    pear  medium    7.0

(3) 左连接

how=‘left’,dataframe的链接方式为左连接,我们可以理解基于左边位置dataframe的列进行连接,参数on设置连接的共有列名;
左边的表的数据都会出现在结果里,右边的如果无法匹配,则为NaN

	 df3 = pd.merge(df1,df2,how='left',on='alpha')
	 print(df3)
#输出结果:
				   alpha  col1    col2  pazham  kilo  price
				0     A     1     low   apple  high    5.0
				1     A     1     low   orange  low    6.0
				2     B     1   medium   pine  high    5.0
				3     B     2   medium   pine  high    5.0
				4     C     3    high     NaN   NaN    NaN
				5     D     3     low     NaN   NaN    NaN
				6     E     1    high     NaN   NaN    NaN
因为df2的连接列alpha有两个'A'值,所以左连接的df5有两个'A'值,若两个dataframe间除了on设置的连接列外并无相同列,则该列的值置为NaN。

(4) 右连接

how=‘right’,dataframe的链接方式为左连接,我们可以理解基于右边位置dataframe的列进行连接,参数on设置连接的共有列名;
右边的表的数据都会出现在结果里,左边的如果无法匹配,则为NaN

	df3 = pd.merge(df1,df2,how='right',on='alpha')
	print(df3)
#输出结果:
			    alpha  col1    col2  pazham    kilo  price
			0     A   1.0     low   apple    high      5
			1     A   1.0     low  orange     low      6
			2     B   1.0  medium    pine    high      5
			3     B   2.0  medium    pine    high      5
			4     F   NaN     NaN    pear  medium      7

(5) 基于多列的连接算法

多列连接的算法与单列连接一致,可自己编码或者图解方式去理解外连接和左连接。
前提是:要做连接的表有多个共同列

#与单列用法一样,不再详细说明
# 基于共同列column1和column2的右连接
df3 = pd.merge(df1,df2,on=['column1','column2'],how='right')   

(6) 基于index的连接方法

# 基于df1的beta列和df2的index连接
df3 = pd.merge(df1,df2,how='inner',left_on='beta',right_index=True,suffixes=('_df1','_df2'))
#输出结果:
		    alpha_df1  col1    col2     alpha_df2  pazham    kilo    price
		0         A     1       low         A      orange     low      6
		1         B     1     medium        A      orange     low      6




    

		5         E     1      high         A      orange     low      6
		2         B     2     medium        B       pine      high     5
		3         C     3      high         F       pear     medium    7
		4         D     3       low         F       pear     medium    7

(7) 若出现非key的字段重名怎么办?

比如出现列名相同,pandas默认添加列名后缀,a_x a_y

	df3 = pd.merge(df1,df2,how='left',on='key',shuffiwes=("_left","_right"))

2、Join

Join方法:基于index连接dataframe,merge方法是基于column连接,连接方法有内连接,外连接,左连接和右连接,默认情况下它是把行索引相同的数据合并在一起,

# 自定义两个数据:
	A= pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3', 'K4', 'K5'], 
	                  'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
	B= pd.DataFrame({'key': ['K0', 'K1', 'K2'],
					  'B': ['B0', 'B1', 'B2']})
	print(A,B)
#输出结果:
			  key   A                            key   B
			0  K0  A0                          0  K0  B0
			1  K1  A1                          1  K1  B1
			2  K2  A2                          2  K2  B2
			3  K3  A3
			4  K4  A4
			5  K5  A5
(1) 内连接
# lsuffix和rsuffix设置连接的后缀名 #在这个数据上,右连接结果与内连接一样(由数据决定)
	afterJoin = A.join(B,lsuffix='_A', rsuffix='_B',how='inner')
	afterJoin = A.join(B, lsuffix='_A', rsuffix='_B', how='right')  
	print(afterJoin)
 #输出结果:可以看出只合并两数据中共同的key
		      key_A    A       key_B    B
		0      K0     A0        K0      B0
		1      K1     A1        K1      B1
		2      K2     A2        K2      B2
(2) 基于key列进行连接 set_index()
	A.set_index('key').join(B.set_index('key'),how='inner')
#输出结果:
		      A   B
		K0   A0  B0
		K1   A1  B1
		K2   A2  B2
(3) 全连接
#在这个数据上,全连接的结果与左连接一样
	afterJoin = A.join(B, lsuffix='_A', rsuffix='_B', how='left')
	afterJoin = A.join(B, lsuffix='_A', rsuffix='_B', how='outer')   
	print(afterJoin)
#输出结果:
		  key_A   A  key_B   B
		0    K0  A0    K0   B0
		1    K1  A1    K1   B1
		2    K2  A2    K2   B2
		3    K3  A3   NaN  NaN
		4    K4  A4   NaN  NaN
		5    K5  A5   NaN  NaN

3、数据拼接 concat()

适用于:批量合并相同格式的Excel、给DataFrame添加行、列
concat方法是拼接函数,有行拼接和列拼接,默认是行拼接,拼接方法默认是外拼接(并集),拼接的对象是pandas数据类型。

  • 使用某中合并方式 inner/outer
  • 沿着某一轴向 axis=0 axis=1
  • 把多个pandas对象合并成一个
concat()语法
	pandas.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
	          keys=None, levels=None, names=None, verify_integrity=False,
	          copy=True)
  • objs:Series,DataFrame或Panel对象的序列或映射。如果传递了dict,则排序的键将用作键参数,除非它被传递,在这种情况下,将选择值(见下文)。任何无对象将被静默删除,除非它们都是无,在这种情况下将引发一个ValueError。
  • axis:{0,1,…},默认为0,代表按行合并;若为1,则按列合并
  • join:{‘inner’,‘outer’},索引的对齐方式;默认为“outer”;outer为联合和inner为交集。
  • ignore_index:boolean,default False。是否忽略掉原来的数据索引
  • 如果为True,请不要使用并置轴上的索引值。结果轴将被标记为0,…,n-1。如果要连接其中并置轴没有有意义的索引信息的对象,这将非常有用。注意,其他轴上的索引值在连接中仍然受到尊重。
  • join_axes:Index对象列表。用于其他n-1轴的特定索引,而不是执行内部/外部设置逻辑。新版本pandas已经删除了join_axes,所以习惯了两个dataframe按照同一列合并的话,可以改用merge:
  • keys:序列,默认值无。使用传递的键作为最外层构建层次索引。如果为多索引,应该使用元组。
  • levels:序列列表,默认值无。用于构建MultiIndex的特定级别(唯一值)。否则,它们将从键推断。
  • names:list,default无。结果层次索引中的级别的名称。
  • verify_integrity:boolean,default False。检查新连接的轴是否包含重复项。这相对于实际的数据串联可能是非常昂贵的。
  • copy:boolean,default True。如果为False,请勿不必要地复制数据。
append()语法

append只有按行合并,没有按列合并,相当于concat按行的简写形式

	DataFrame.append(other,ignore_index=False)

参数说明:

  • other:单个dataframe、series、dict或者列表
  • ignore_index:是否忽略掉原来的数据索引

(1) series类型的拼接方法

df1 = pd.Series([1.1, 2.2, 3.3],index=['i1','i2','i3'])
df2 = pd.Series([4.4, 5.5, 6.6],index=['i2','i3','i4'])
#数据结构为:
	i1    1.1					i2    4.4
	i2    2.2					i3    5.5
	i3    3.3					i4    6.6
	dtype: float64				dtype: float64
# 对行拼接分组
pd.concat([df1,df2],keys=['fea1','fea2'])   
#行拼接若有相同的索引,为了区分索引,可以在最外层定义了索引的分组情况,若没有可以不设置keys属性
#结果为:
				fea1  i1    1.1
				      i2    2.2
				      i3    3.3
				fea2  i2    4.4
				      i3    5.5
				      i4    6.6
				dtype: float64

列拼接默认以并集的方式拼接

pd.concat([df1,df2],axis=1)
#输出结果:
				i1  1.1  NaN
				i2  2.2  4.4
				i3  3.3  5.5
				i4  NaN  6.6
列拼接的内连接(交集)
pd.concat([df1,df2],axis=1,join='inner')
#输出结果:
				i2  2.2  4.4
				i3  3.3  5.5
# 设置列名
pd.concat([df1,df2],axis=1,join='inner',keys=[




    
'fea1','fea2'])
#输出结果:
				    fea1  fea2
				i2   2.2   4.4
				i3   3.3   5.5

(2) dataframe类型的拼接方法

#定义dataframe类型的数据
	df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3', 'K4', 'K5'],
						 'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
	df2 = pd.DataFrame({'key': ['K0', 'K1', 'K2'],
						'B': ['B0', 'B1', 'B2']})
	print(df1)
	print(df2)
#打印数据:
				  key   A				   key   B
				0  K0  A0				0  K0  B0	
				1  K1  A1				1  K1  B1
				2  K2  A2				2  K2  B2
				3  K3  A3
				4  K4  A4
				5  K5  A5
	df3 = pd.concat([df1,df2])
	print(df3)
#输出结果:
							  key    A    B
							0  K0   A0  NaN
							1  K1   A1  NaN
							2  K2   A2  NaN
							3  K3   A3  NaN
							4  K4   A4  NaN
							5  K5   A5  NaN
							0  K0  NaN   B0
							1  K1  NaN   B1
							2  K2  NaN   B2
#若列名均不相同:
							  key1    A key2    B
							0   K0   A0  NaN  NaN
							1   K1   A1  NaN  NaN
							2   K2   A2  NaN  NaN
							3   K3   A3  NaN  NaN
							4   K4   A4  NaN  NaN
							5   K5   A5  NaN  NaN
							0  NaN  NaN   K0   B0
							1  NaN  NaN   K1   B1
							2  NaN  NaN   K2   B2
#用append添加行数据
	df2 = df2.append({"key": K3,,"B":B3}, ignore_index = True)
#结果为:
  			   key   B  
			0  K0   B0
			1  K1   B1
			2  K2   B2
			3  K3   B3
	pd.concat([df1,df2],axis=1) 
#输出结果:
							  key   A  key    B
							0  K0  A0   K0   B0
							1  K1  A1   K1   B1
							2  K2  A2   K2   B2
							3  K3  A3  NaN  NaN
							4  K4  A4  NaN  NaN
							5  K5  A5  NaN  NaN
df3 = pd.concat([df1,df2],axis=1,verify_integrity = True)
# 设置verify_integrity = True;若列拼接或行拼接有重复的列名和行名,则报错
#添加一列series
s1 = pd.Series(list(range(3),name="F"))
pd.concat([df2,s1],axis=1) 
#结果为:
  			   key   B   F
			0  K0  B0	 0
			1  K1  B1	 1
			2  K2  B2	 2
#添加多列series
s1 = pd.Series(list(range(3),name="F"))
s2 = DF2.apply(lambda x : x["B"]+"_G", axis=1)
pd.concat([df2,s1,s2],axis=1) 
#结果为:
  			   key   B   F	  E
			0  K0   B0	 0	 B0_G
			1  K1   B1	 1	 B1_G
			2  K2   B2	 2	 B2_G

二、数据分组与聚合

1、分组 — groupby

  • 对数据集进行分组,然后对每组上应用聚合函数、转换函数
  • SQL能够对数据进行过滤,分组聚合
  • pandas能利用groupby进行更加复杂的分组运算
  • 分组运算过程:split->apply->combine
    • 拆分:进行分组的根据
    • 应用:每个分组运行的计算规则
    • 合并:把每个分组的计算结果合并起来

DataFrame.groupby(key, as_index=False)

  • GroupBy对象:DataFrameGroupBy,SeriesGroupBy
  • key:分组的列数据,可以多个
  • groupby()进行分组,GroupBy对象没有进行实际运算,只是包含分组的中间数据
(1)单列分组
#以pm2.5数据为例
	data = pd.read_csv( 'pm25_data_2010.1.1-2014.12.31.csv')
#No  year  month  day  hour  pm2.5  ...  TEMP    PRES  cbwd     Iws  Is  Ir
#先分组再取列 ,按照列名分组
	newData = data.groupby(['month'])['pm2.5'].count()
#count():统计该组元素的个数
#先取列,再分组
	newData = data['pm2.5'].groupby(data['month']).count()    #一样的结果
	print(newData)
#输出结果:  按照month分组,计算pm2.5的统计信息
		  month
			1     3471
			2     3373
			3     3556
			4     3405
			5     3609
			6     3405
			7     3647
			8     3337
			9     3333
			10    3579
			11    3501
			12    3541
			Name: pm2.5, dtype: int64
#不作为索引
	newData = data.groupby(['month'],as_index=False)['pm2.5'].count()
	print(newData)
#输出结果:
			    month  pm2.5
			0       1   3471
			1       2   3373
			2       3   3556
			3       4   3405
			4       5   3609
			5       6   3405
			6       7   3647
			7       8   3337
			8       9   3333
			9      10   3579
			10     11   3501
			11     12   3541
(2) 多列分组
	grouped2 = data.groupby(['year', 'cbwd']).count()
	print(grouped2)
输出结果:                                                             
			year  cbwd
			2010  0       2887
			      ...      ...
			2011  0       2900
			      ...      ...
			2012  0       2581
			      ...      ...
			2013  0       2690
			      ...      ...
			2014  0       2426
			      ...      ...
			      3       3186
Name: pm2.5, dtype: int64
# GroupBy对象转换list
	print(list(grouped2))
输出结果:
	[2887, 1545, 899, 2760, 2900, 1628, 832, 2672, 2581, 1799, 985, 2930, 2690, 1916, 1047, 					3025, 2426, 2056, 993, 3186]
(3) 按照数值类型dtypes分组
	newData = data.groupby(data.dtypes, axis=1).size()
	print(newData )
#输出结果:
			int64      9
			float64    4
			dtype: int64

二、聚合 — aggregation

数组产生标量的过程,如mean()、count()等;常用于对分组后的数据进行计算
内置的聚合函数:sum(), mean(), max(), min(), count(), size(), describe(),std(), var()

函数名说明
count分组中非NaN的值的数量
sum非NaN值的和
mean非NaN值的平均值
median非NaN值的算术中位数
std、var无偏(分母为n-1) 标准差、方差
min、max非NaN值的最小值、最大值
prod非NaN值的乘积
first、last第一个、最后一个非NaN值
在pandas中对数据进行分组后,想要对相同组的数据进行其他字段的合并。类似场景:有2个字段,分别是文本内容和标签值。先根据文本内容进行分组,再对同一个组内的标签值进行合并,从而得到多标签值。 import pandas as pd df = pd.DataFrame({'text': ['华中科技大学', '武汉大学', '清华大学', '华中科技大学', '武汉大学'], 'label': ["985,理工", "985" 1. maybe a semicolon is missing before `value toDF'? 2. DataFrame 创建与保存 3. Mysql 数据库的读取与写入 4. Hive 数据仓库的读取与写入 例子:df_fund = pd.merge( df_fund, df_perf , left_on=“基金代码”, right_on=“基金代码” ) left_on=“基金代码”, right_on=“基金代码” 会导致合并后的df有2个columns:“基金代码_x”,"“基金代码”_y" 解决方法: df_fund = pd.merge( df_fund, df_perf , on=“基金代码”) 使用read_csv()函数读取step3文件夹中的state-population.csv(pop)、state-areas.csv(areas)、state-abbrevs.csv(abbrevs)文件; 合并pop和abbrevs。我们需要将pop的state/region列与abbrevs的abbreviation列进行合并,还需要通过how='outer'. Pandas提供了concat、append、join和merge四种方法用于dataframe的拼接,其大致特点和区别见下表: .concat() pandas的顶级方法,提供了axis设置可用于df间行方向(增加行,下同)或列方向(增加列,下同)进行内联或外联拼接操作 .append() dataframe数据类型的方法,提供了行方向的拼接操作 .join() datafr... sku_tot_vol = data['unuseble_volume'].groupby([data.sku,data.location_code,data.unuseble_volume]).sum() df....