Merge, Join, Concat大家好,我有回来啦,这周更新的有点慢,主要是因为我更新了个人简历哈哈,如果感兴趣的朋友可以去看看哈:我的主页个人认为还是很漂亮的~,不得不说,很多时候老外的设计能力还是很强。好了,有点扯远了,这一期我想和大家分享的是pandas中最常见的几种方法,这些方法如果你学会了,某种程度上可以很好的替代Excel,这篇文章是pandas之旅的第三篇,主要会从以下几个方面和大家分享我的心得体会:MergeJoinConcat源码及GitHub地址话不多说,让我们开始今天的Pandas之旅吧!1. Merge首先merge的操作非常类似sql里面的join,实现将两个Dataframe根据一些共有的列连接起来,当然,在实际场景中,这些共有列一般是Id,连接方式也丰富多样,可以选择inner(默认),left,right,outer 这几种模式,分别对应的是内连接,左连接,右连接1.1 InnerMerge (内连接)首先让我们简单的创建两个DF,分别为DataFrame1,DataFrame2,他们的公有列是keyimport numpy as npimport pandas as pdfrom pandas import Series, DataFrame# Let’s make a dframedframe1 = DataFrame({‘key’:[‘X’,‘Z’,‘Y’,‘Z’,‘X’,‘X’],‘value_df1’: np.arange(6)})dframe1 key value_df1 0 X 0 1 Z 1 2 Y 2 3 Z 3 4 X 4 5 X 5 #Now lets make another dframedframe2 = DataFrame({‘key’:[‘Q’,‘Y’,‘Z’],‘value_df2’:[1,2,3]})dframe2 key value_df2 0 Q 1 1 Y 2 2 Z 3 我们现在可以简单地使用pd.merge(dframe1,dframe2)来实现Merge功能pd.merge(dframe1,dframe2) key value_df1 value_df2 0 Z 1 3 1 Z 3 3 2 Y 2 2 我们现在需要注意一点,X仅仅是存在于dframe1的key,在dframe2中不存在,因此大家可以发现,当我们调用pd.merge的时候,会自动默认为inner join,我们再换一种方式写一下,大家就明白了:pd.merge(dframe1,dframe2,on=‘key’,how=‘inner’) key value_df1 value_df2 0 Z 1 3 1 Z 3 3 2 Y 2 2 大家可以发现结果是一样的,看到这里,对sql熟悉的朋友们已经有感觉了估计,因为实在是太像了,如果我们不通过on和how来指定想要merge的公有列或者方式,那么pd.merge就会自动寻找到两个DataFrame的相同列并自动默认为inner join,至此,估计大家也可以猜出其他几种模式的merge啦1.2 LeftMerge (左连接)现在同样的,让我们看一下how=‘left’的情况,这是一个左连接pd.merge(dframe1,dframe2,on=‘key’,how=‘left’) key value_df1 value_df2 0 X 0 NaN 1 Z 1 3.0 2 Y 2 2.0 3 Z 3 3.0 4 X 4 NaN 5 X 5 NaN 我们可以看到返回的是dframe1的所有key值对应的结果,如果在dframe2中不存在,显示为Nan空值1.3 RightMerge (右连接)右连接的原理和左连接正相反pd.merge(dframe1,dframe2,on=‘key’,how=‘right’) key value_df1 value_df2 0 Z 1.0 3 1 Z 3.0 3 2 Y 2.0 2 3 Q NaN 1 这里Q只存在于drame2的key中1.4 OuterMerge (全连接)#Choosing the “outer” method selects the union of both keyspd.merge(dframe1,dframe2,on=‘key’,how=‘outer’) key value_df1 value_df2 0 X 0.0 NaN 1 X 4.0 NaN 2 X 5.0 NaN 3 Z 1.0 3.0 4 Z 3.0 3.0 5 Y 2.0 2.0 6 Q NaN 1.0 这里就是一个并集的形式啦,其实就是一个union的结果,会把key这一列在两个Dataframe出现的所有值全部显示出来,如果有空值显示为Nan1.5 MultipleKey Merge (基于多个key上的merge)刚才我们都是仅仅实现的在一个key上的merge,当然我们也可以实现基于多个keys的merge# Dframe on leftdf_left = DataFrame({‘key1’: [‘SF’, ‘SF’, ‘LA’], ‘key2’: [‘one’, ’two’, ‘one’], ’left_data’: [10,20,30]})df_left key1 key2 left_data 0 SF one 10 1 SF two 20 2 LA one 30 #Dframe on rightdf_right = DataFrame({‘key1’: [‘SF’, ‘SF’, ‘LA’, ‘LA’], ‘key2’: [‘one’, ‘one’, ‘one’, ’two’], ‘right_data’: [40,50,60,70]})df_right key1 key2 right_data 0 SF one 40 1 SF one 50 2 LA one 60 3 LA two 70 这是内连接(交集)的结果#Merge, Innerpd.merge(df_left, df_right, on=[‘key1’, ‘key2’]) key1 key2 left_data right_data 0 SF one 10 40 1 SF one 10 50 2 LA one 30 60 这是外连接(并集)的结果#Merge, Outerpd.merge(df_left, df_right, on=[‘key1’, ‘key2’],how=‘outer’) key1 key2 left_data right_data 0 SF one 10.0 40.0 1 SF one 10.0 50.0 2 SF two 20.0 NaN 3 LA one 30.0 60.0 4 LA two NaN 70.0 这里还有一个地方非常有意思,大家可以发现现在df_left,df_right作为key的两列分别是key1和key2,它们的名字是相同的,刚刚我们是通过制定on=[‘key1’, ‘key2’],那如果我们只指定一列会怎么样呢?pd.merge(df_left,df_right,on=‘key1’) key1 key2_x left_data key2_y right_data 0 SF one 10 one 40 1 SF one 10 one 50 2 SF two 20 one 40 3 SF two 20 one 50 4 LA one 30 one 60 5 LA one 30 two 70 大家可以看到pandas自动把key2这一列拆分成了key2_x和key2_y,都会显示在最后的merge结果里,如果我们想要给这两列重新命名,也是很容易的:# We can also specify what the suffix becomespd.merge(df_left,df_right, on=‘key1’,suffixes=(’_lefty’,’_righty’)) key1 key2_lefty left_data key2_righty right_data 0 SF one 10 one 40 1 SF one 10 one 50 2 SF two 20 one 40 3 SF two 20 one 50 4 LA one 30 one 60 5 LA one 30 two 70 像这样,我们可以通过suffixes参数来指定拆分的列的名字。1.6 Merge on Index (基于index上的merge)我们还可以实现几个Dataframe基于Index的merge,还是老样子,先让我们创建两个Dataframedf_left = DataFrame({‘key’: [‘X’,‘Y’,‘Z’,‘X’,‘Y’], ‘data’: range(5)})df_right = DataFrame({‘group_data’: [10, 20]}, index=[‘X’, ‘Y’])df_left key data 0 X 0 1 Y 1 2 Z 2 3 X 3 4 Y 4 df_right group_data X 10 Y 20 好了,现在我们想要实现两个Dataframe的merge,但是条件是通过df_left的Key和df_right的Indexpd.merge(df_left,df_right,left_on=‘key’,right_index=True) key data group_data 0 X 0 10 3 X 3 10 1 Y 1 20 4 Y 4 20 这样我们也可以得到结果。# We can also get a union by using outerpd.merge(df_left,df_right,left_on=‘key’,right_index=True,how=‘outer’) key data group_data 0 X 0 10.0 3 X 3 10.0 1 Y 1 20.0 4 Y 4 20.0 2 Z 2 NaN 其他的merge方式就类似啦,这里就不一一说了,只是举一个outer join的例子# 通过outer实现外连接,union并集pd.merge(df_left,df_right,left_on=‘key’,right_index=True,how=‘outer’) key data group_data 0 X 0 10.0 3 X 3 10.0 1 Y 1 20.0 4 Y 4 20.0 2 Z 2 NaN 我们也可以尝试一些有意思的merge,比如,如果一个dataframe的index是多层嵌套的情况:df_left_hr = DataFrame({‘key1’: [‘SF’,‘SF’,‘SF’,‘LA’,‘LA’], ‘key2’: [10, 20, 30, 20, 30], ‘data_set’: np.arange(5.)})df_right_hr = DataFrame(np.arange(10).reshape((5, 2)), index=[[‘LA’,‘LA’,‘SF’,‘SF’,‘SF’], [20, 10, 10, 10, 20]], columns=[‘col_1’, ‘col_2’])df_left_hr key1 key2 data_set 0 SF 10 0.0 1 SF 20 1.0 2 SF 30 2.0 3 LA 20 3.0 4 LA 30 4.0 df_right_hr col_1 col_2 LA 20 0 1 10 2 3 SF 10 4 5 10 6 7 20 8 9 现在我们穿建了两个Dataframe 分别是df_left_hr和df_right_hr(Index两层),如果我们想通过使用df_left_hr的key1,key2 及df_right_hr的Index作为merge的列,也是没有问题的# Now we can merge the left by using keys and the right by its indexpd.merge(df_left_hr,df_right_hr,left_on=[‘key1’,‘key2’],right_index=True) key1 key2 data_set col_1 col_2 0 SF 10 0.0 4 5 0 SF 10 0.0 6 7 1 SF 20 1.0 8 9 3 LA 20 3.0 0 1 基本到这里,我已经和大家分享了基础的Merge有关的所有操作,如果你平时生活工作中经常使用Excel执行类似操作的话,可以学习一下Merge哈,它会大幅度减轻你的工作强度的!2.Join现在我们可以接着来看join相关的操作,先让我们看一个小例子left = pd.DataFrame({‘A’: [‘A0’, ‘A1’, ‘A2’, ‘A3’], ‘B’: [‘B0’, ‘B1’, ‘B2’, ‘B3’]}, index = [‘K0’, ‘K1’, ‘K2’, ‘K3’]) right = pd.DataFrame({‘C’: [‘C0’, ‘C1’, ‘C2’, ‘C3’], ‘D’: [‘D0’, ‘D1’, ‘D2’, ‘D3’]}, index = [‘K0’, ‘K1’, ‘K2’, ‘K3’]) left A B K0 A0 B0 K1 A1 B1 K2 A2 B2 K3 A3 B3 right C D K0 C0 D0 K1 C1 D1 K2 C2 D2 K3 C3 D3 left.join(right) A B C D K0 A0 B0 C0 D0 K1 A1 B1 C1 D1 K2 A2 B2 C2 D2 K3 A3 B3 C3 D3 其实通过这一个小例子大家也就明白了,join无非就是合并,默认是横向,还有一个点需要注意的是,我们其实可以通过join实现和merge一样的效果,但是为了避免混淆,我不会多举其他的例子了,因为我个人认为一般情况下还是用merge函数好一些3. Concat为了更加全面彻底地了解Concat函数,大家可以先从一维的Numpy Array开始,首先让我们简单的创建一个矩阵:# Create a matrix arr1 = np.arange(9).reshape((3,3))arr1array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])接着让我们通过concatenate函数进行横向拼接:np.concatenate([arr1,arr1],axis=1)array([[0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5], [6, 7, 8, 6, 7, 8]])再让我们进行纵向拼接:# Let’s see other axis optionsnp.concatenate([arr1,arr1],axis=0)array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 1, 2], [3, 4, 5], [6, 7, 8]])有了基础的印象之后,现在让我们看看在pandas中是如何操作的:# Lets create two Series with no overlapser1 = Series([0,1,2],index=[‘T’,‘U’,‘V’])ser2 = Series([3,4],index=[‘X’,‘Y’])#Now let use concat (default is axis=0)pd.concat([ser1,ser2])T 0U 1V 2X 3Y 4dtype: int64在上面的例子中,我们分别创建了两个没有重复Index的Series,然后用concat默认的把它们合并在一起,这时生成的依然是Series类型,如果我们把axis换成1,那生成的就是Dataframe,像下面一样pd.concat([ser1,ser2],axis=1,sort =True) # sort=Ture是默认的,pandas总是默认index排序 0 1 T 0.0 NaN U 1.0 NaN V 2.0 NaN X NaN 3.0 Y NaN 4.0 我们还可以指定在哪些index上进行concat:pd.concat([ser1,ser2],axis=1,join_axes=[[‘U’,‘V’,‘Y’]]) 0 1 U 1.0 NaN V 2.0 NaN Y NaN 4.0 也可以给不同组的index加一层标签pd.concat([ser1,ser2],keys=[‘cat1’,‘cat2’])cat1 T 0 U 1 V 2cat2 X 3 Y 4dtype: int64如果把axis换成是1,那么keys就会变成column的名字:pd.concat([ser1,ser2],axis=1,keys=[‘cat1’,‘cat2’],sort=True) cat1 cat2 T 0.0 NaN U 1.0 NaN V 2.0 NaN X NaN 3.0 Y NaN 4.0 如果是两个现成的dataframe直接进行concat也是一样:dframe1 = DataFrame(np.random.randn(4,3), columns=[‘X’, ‘Y’, ‘Z’])dframe2 = DataFrame(np.random.randn(3, 3), columns=[‘Y’, ‘Q’, ‘X’])dframe1 X Y Z 0 1.119976 -0.853960 0.027451 1 -0.536831 0.982092 -0.157650 2 -0.219322 -1.489809 1.607735 3 0.767249 -1.661912 0.038837 dframe2 Y Q X 0 -0.035560 0.875282 -1.630508 1 -0.439484 0.096247 1.335693 2 0.746299 0.568684 1.197015 #如果没有对应的值,默认为NaN, 空值pd.concat([dframe1,dframe2],sort=True) Q X Y Z 0 NaN 1.119976 -0.853960 0.027451 1 NaN -0.536831 0.982092 -0.157650 2 NaN -0.219322 -1.489809 1.607735 3 NaN 0.767249 -1.661912 0.038837 0 0.875282 -1.630508 -0.035560 NaN 1 0.096247 1.335693 -0.439484 NaN 2 0.568684 1.197015 0.746299 NaN 4. 源码及Github地址今天我为大家主要总结了pandas中非常常见的三种方法:mergeconcatjoin大家可以根据自己的实际需要来决定使用哪一种我把这一期的ipynb文件和py文件放到了Github上,大家如果想要下载可以点击下面的链接:Github仓库地址: https://github.com/yaozeliang/pandas_share这一期就到这里啦,希望大家能够继续支持我,完结,撒花
...