<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 数据合并、连接和拼接 Merge, join, and concatenate
对于Series DataFrame和Panel对象，pandas提供了丰富的对象之间的连接、合并操作
专业术语-中英文对照
|    英语     | 汉语  | 
| ------------- |
Step1:  使用join='inner' 查看结果 ,和outer一样！
Step2:  修改df3的index，看看结果
Step3:  修改df5，使得某几行和df2一样，再看看结果
Step4:  如同numpy.concatenate()方法, pandas.concat方法接收一个列表或者字典对象然后进行拼接操作，注意列表或字典中每个对象要是同构的。拼接的本质就是沿着一条轴并且根据对另一条轴上进行的操作 将列表中的对象堆叠。
concat方法的参数
Step5:  注意到结果中的索引是层次化的。
Step6:  注意：concat()方法在拼接使要复制所有的数据，因此对于它的性能你要容忍。为了方便起见，如果对多个数据集拼接，可以使用列表解析式。
Step7:  对其它轴进行逻辑运算 Set logic on the other axes
如果是对DataFrame或Panel对象进行拼接操作，你可以同时对非拼接轴进行逻辑运算。由于Series只有一个轴，所以此功能不适用于Series对象。
有三种方式能够对非拼接轴进行逻辑运算：
* join='outer',取并集，这也是默认的操作，这个操作绝会有信息损失。
* join='inner',取交集。
* 利用join_axes参数。
针对上面三种方法，各举一例说明：
Step8:  解释：
axis=1，即拼接轴是横轴，先将df1的列和df4的列名进行堆叠，即每一行有7列。由于join='outer', 故将df1和df4的索引取取并集，得到{0,1,2,3,6,7},共6行。
还要注意结果的索引值是排好序的。
Step9:  再来看看join='inner'的例子：
Step10:  解释：
axis=1，即拼接轴是横轴，先将df1的列和df4的列名进行堆叠，即每一行有7列。由于join='inner', 故将df1和df4的索引取取并集，得到{2,3},共2行。
还要注意结果的索引值没有排序。
最后，看一下使用 join_axes参数的例子：
Step11:  解释：
axis=1，即拼接轴是横轴，先将df1的列和df4的列名进行堆叠，即每一行有7列。由于join_axes=[df1.index]，故结果的索引取值和df1相同，{0,1,2,3}。
使用append()方法进行 行拼接
如果只想对Series或DataFrame对象进行行拼接(axis=0)，推荐使用append()方法。 append()方法实际上就是沿着索引轴(axis=0)进行拼接的concat()。
注意：
如果是对DataFrame对象进行append操作，要注意他们的索引值交集必须为空！即每个DataFrame对象的索引值都不相同。列名不作要求。
其实，对DataFrame进行append操作时是可以忽略索引的，result = df1.append(df4, ignore_index=True)
Step12:  
Step13:  append()方法可以一次拼接多个对象。
Step14:  append()操作并不是直接对df1对象进行操作，而是在df1副本的基础上进行拼接操作。
拼接操作时忽略索引值
大多数情况下，索引值都是默认生成的一些无意义的id，此时，两个DataFrame对象很可能有重复的索引值，但他们并没有实质物理含义，此时，在进行行拼接操作时我们可以忽略索引，使用ignore_index参数即可。
在进行列拼接时，就不要使用ignore_index参数了，因为99.9999%的数据列名都是有意义的。
Step15:  DataFrame.append方法也有ignore_index参数哦
Step16:  同时对Series和DataFrame对象进行拼接操作
很简单，原因就是Series会被隐式转为DataFrame对象，同时保持列名相同
Step17:  如果Series的列没有名字，会默认生成数字用于列名。
Step18:  对Series对象进行拼接时使用keys参数
concat()方法中keys参数除了构建层次化索引外，另一个很常见的使用情景是：对多个Series对象进行拼接操作，我们希望重新制定得到的DataFrame对象中的列名，而不是使用Series中的名字。
Step19:  通过keys参数，来设置生成的DataFrame的列名
Step20:  回顾一下我们的第一个例子
Step21:  可以用字典代替上面concat方法中的frames和keys
Step22:  
Step23:  对DataFrame对象增加行数
你可以使用append()方法接收一个Series或者列表 对DataFrame对象增加一行，虽然这种方法效率不高,因为要重新生成一个新的DataFrame存放结果。
也可以传递一个Series构成的列表或者字典构成的列表，来增加几行！
Step24:  数据库风格的DataFrame 连接/合并操作
pandas提供了非常高效的DataFrame连接(join)操作，并且使用风格和SQL非常类似。相对于其他的开源实现，pandas无疑是相当高效的, 这要归功于对DataFrame对象的优秀的算法设计和高效的内部数据部署。
如果你之前有过SQL开发经验而首次使用pandas，你可能想先了解二者的对比。
pandas仅提供了一个merge()方法，就能够对DataFrame对象进行类似关系数据库的连接(join)操作，先看merge()参数
merge(left, right, how='inner', on=None, left_on=None, right_on=None,
      left_index=False, right_index=False, sort=True,
      suffixes=('_x', '_y'), copy=True, indicator=False)
left
Step25:  解释
Step26:  解释
Step27:  解释：
on的参数是['key1', 'key2'],所以拼接的键值是['key1', 'key2']，how参数是'left',所以进行的是左拼接，只关注left中键值取值。
过程：left中第一行键值是['K0', 'K1'],发现right有此取值，拼接后得到result中的第一行；
left中第二行键值是['K0', 'K1'],发现right中没有此取值，仍进行拼接得到result中第二行，注意'C' 'D'取值NaN
left中第三行键值是['K1', 'K0'], 发现right中有此取值切出现了两次，分别进行拼接得到result中第三行、第四行
left中第四行取值是['K2', 'K1'], 发现right中没有此取值，仍进行拼接得到result中第五行，'C', 'D'取值NaN
Step28:  
Step29:  
Step30:  merge方法中indicator参数说明
0.17.0版本才有的参数
merge方法在0.17.0版本中新增了一个参数indicator。这个参数取值True，False或字符串。如果取值True，会在拼接结果中多出一列'_merge', 显示 每一行的键值来自left还是right。
|    _merge值     | 含义|
| ------------- |
Step31:  上面提到indicator参数取值也可以是字符串，没啥特别的，就是在拼接结果中用接收的字符串作为'_merge'的列名罢了。
Step32:  对索引进行拼接
DataFrame.join方法的作用是对两个DataFrame对象进行基于索引值的拼接操作。下面是一个简单的例子
Step33:  
Step34:  
Step35:  merge方法中提供了left_index, right_index参数同样实现了基于索引的拼接操作。
Step36:  
Step37:  除拼接键值之外，重复的列名用suffixes参数区别
很多情况下，left和right中除了拼接键值之外，还会有其他列名也相同，为了在结果中加以区分，这个时候suffixes参数就派上用场了。好消息是suffixes有默认值，即使不为它赋值在结果中也能够区分。
举例如下：
Step38:  默认情况下：
Step39:  DataFrame.join方法也提供了lsuffix和rsuffix参数来实现同样的功能
Step40:  拼接多个DataFrame对象
DataFrame.join方法能够接收DataFrame对象构成的元组或列表，对列表内所有DF对象进行基于索引的拼接。Panel.join方法也有此功能。
Step41:  合并 有序数据
v0.18.0新增了一个ordered_merge()方法 对时间序列或者其他有序数据进行合并。并且ordered_merge提供了fill_method参数来填充缺失值。
Step42:  使用合并方法填充NaN
Step43:  先使用combine_first方法：
Step44:  df1和df2列名完全相同，索引值也相似。
由于df2中不存在索引值=0，所以df1中第一行的值原封不动；
对于df1中不等于NaN的值，也不需要改变；
对于df1中等于NaN的值，用df2中同索引同列名的值替换， 得到结果。
注意combine_first()方法不改变df1的值。
如果想改变df1的值，使用update()方法。
<ASSISTANT_TASK:>
Python Code:
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'A':['A0','A1','A2','A3'],
                    'B':['B0','B1','B2','B3'],
                    'C':['C0','C1','C2','C3'],
                    'D':['D0','D1','D2','D3']},
                   index=[0,1,2,3])
df1
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
                   'B': ['B4', 'B5', 'B6', 'B7'],
                   'C': ['C4', 'C5', 'C6', 'C7'],
                   'D': ['D4', 'D5', 'D6', 'D7']},
                   index=[4, 5, 6, 7])
df2
df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
                   'B': ['B8', 'B9', 'B10', 'B11'],
                   'C': ['C8', 'C9', 'C10', 'C11'],
                   'D': ['D8', 'D9', 'D10', 'D11']},
                   index=[8, 9, 10, 11])
df3
frames = [df1, df2, df3] #产生一个list对象
results = pd.concat(frames)
results
Explanation: 数据合并、连接和拼接 Merge, join, and concatenate
对于Series DataFrame和Panel对象，pandas提供了丰富的对象之间的连接、合并操作
专业术语-中英文对照
|    英语     | 汉语  | 
| ------------- |:-------------:| 
| merge      | 合并| 
| join      | 连接      | 
| concat | 拼接      |  
|index|索引|
|list|列表|
|dict|字典|
pandas axis解释
官方：It specifies the axis along which the means are computed.  沿着轴操作。
默认axis=0，也就是竖轴，操作的结果是行数的增加或减少
axis=1，也就是横轴，操作的结果每一列属性增加或减少
拼接操作 Concatenating objects
pandas.concat()方法实现了所有的拼接操作，即沿着一条轴将多个对象堆叠到一起。
提醒：所有使用concat()进行行拼接(axis=1)的操作，都可以转化为使用merge()完成。
concat()拼接时根据两个对象的index进行拼接，可以使用reset_index(),得到两个DataFrame，使用pd.merge(),on=index得到的列。
在讲解复杂的concat操作之前，先看一个简单的示例：
pandas中concat对DataFrame操作, 由axis和join两个参数共同控制得到结果。
axis=0, 结果是行数等于两个子DataFrame的行数之和(结果的索引是两个子DF 索引的罗列，即使子DF的索引重复也无所谓)。而每一行的列数 由join参数控制，如果join=‘outer’，会对两个子DataFrame的列求并集，得到结果的每一行属性；如果join=‘inner’，会对两个子DataFrame的列求交集，得到结果的每一行属性
axis=1, 结果中每一行的属性个数等于两个子DF中的属性相加。而行数由join参数控制，具体地，对子DF的索引进行outer或inner。
End of explanation
res = pd.concat(frames, join='inner')
res
Explanation: 使用join='inner' 查看结果 ,和outer一样！
End of explanation
df5 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
                   'B': ['B8', 'B9', 'B10', 'B11'],
                   'C': ['C8', 'C9', 'C10', 'C11'],
                   'D': ['D8', 'D9', 'D10', 'D11']},
                   index=[2, 3, 10, 11])
df5
df1
results2 = pd.concat([df1,df2,df5])
results2
Explanation: 修改df3的index，看看结果
End of explanation
df5 = pd.DataFrame({'A': ['A2', 'A9', 'A10', 'A11'],
                   'B': ['B2', 'B9', 'B10', 'B11'],
                   'C': ['C2', 'C9', 'C10', 'C11'],
                   'D': ['D2', 'D9', 'D10', 'D11']},
                   index=[2, 3, 10, 11])
df5
results3 = pd.concat([df1,df2,df5])
results3
Explanation: 修改df5，使得某几行和df2一样，再看看结果
End of explanation
#层次化索引， 用处是给列表中每个对象一个map标记，这样在结果中还能方便的调用每个子Series或DataFrame
result = pd.concat(frames, keys=['x','y','z']) 
result
Explanation: 如同numpy.concatenate()方法, pandas.concat方法接收一个列表或者字典对象然后进行拼接操作，注意列表或字典中每个对象要是同构的。拼接的本质就是沿着一条轴并且根据对另一条轴上进行的操作 将列表中的对象堆叠。
concat方法的参数:
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
       keys=None, levels=None, names=None, verify_integrity=False)
objs: Series、DataFrame或Panel对象构成的列表或字典。如果传入一个字典对象，它的键值就作为最后结果的键值参数，除非显示说明结果的键值参数。
axis: 轴，取值范围是{0,1,...}，默认值为0。concat操作时沿着的那条轴
join: 取值范围是{'inner', 'outer'},即内连接(交集)和外连接(并集)。 默认是'outer'(外连接)。连接操作决定了如何处理除axis之外的那条轴。
join_axes: 拼接操作得到的结果，它的索引取值。
keys: 序列对象，默认是None。 构建层次化索引时使用传入的keys作为最外层的索引。如果想要传入多级keys，需要以元组形式传入。
levels: 序列构成的列表，默认是None。用于构建MultiIndex。
names：列表，默认是None。层次索引中每个level的名字。
verify_integrity: 布尔变量，默认是False。用于检查新拼接的轴是否包含重复值。这个操作很耗时。
ignore_index: 布尔变量，默认是False。如果值为True，则不使用拼接轴现有的索引值，拼接结果的索引值将会设置为0,1,...,n-1。
copy: 布尔变量，默认是True。 如果取值为False，则不会复制不必要的数据。
如果不结合例子来看，上面介绍的参数真没法解释。
先来看一下keys参数 用于构建层次化索引时起到的作用。
End of explanation
result.ix['y'] #查看df2
Explanation: 注意到结果中的索引是层次化的。
End of explanation
frames = [process_your_file(f) for f in files]
result = pd.concat(frames)
Explanation: 注意：concat()方法在拼接使要复制所有的数据，因此对于它的性能你要容忍。为了方便起见，如果对多个数据集拼接，可以使用列表解析式。
End of explanation
df4 = pd.DataFrame({'B': ['B2', 'B3', 'B6', 'B7'],
                   'D': ['D2', 'D3', 'D6', 'D7'],
                   'F': ['F2', 'F3', 'F6', 'F7']},
                   index=[2, 3, 6, 7])
result = pd.concat([df1, df4], axis=1) #这里axis=1
Explanation: 对其它轴进行逻辑运算 Set logic on the other axes
如果是对DataFrame或Panel对象进行拼接操作，你可以同时对非拼接轴进行逻辑运算。由于Series只有一个轴，所以此功能不适用于Series对象。
有三种方式能够对非拼接轴进行逻辑运算：
* join='outer',取并集，这也是默认的操作，这个操作绝会有信息损失。
* join='inner',取交集。
* 利用join_axes参数。
针对上面三种方法，各举一例说明：
End of explanation
df4 = pd.DataFrame({'B': ['B2', 'B3', 'B6', 'B7'],
                   'D': ['D2', 'D3', 'D6', 'D7'],
                   'F': ['F2', 'F3', 'F6', 'F7']},
                   index=[3, 2, 7, 6]) #注意这里的索引值序列
df4
result = pd.concat([df1, df4], axis=1) 
result #结果中的索引值已排序
Explanation: 解释：
axis=1，即拼接轴是横轴，先将df1的列和df4的列名进行堆叠，即每一行有7列。由于join='outer', 故将df1和df4的索引取取并集，得到{0,1,2,3,6,7},共6行。
还要注意结果的索引值是排好序的。
End of explanation
result = pd.concat([df1, df4], axis=1, join='inner')
result
Explanation: 再来看看join='inner'的例子：
End of explanation
result = pd.concat([df1, df4], axis=1, join_axes=[df1.index])
Explanation: 解释：
axis=1，即拼接轴是横轴，先将df1的列和df4的列名进行堆叠，即每一行有7列。由于join='inner', 故将df1和df4的索引取取并集，得到{2,3},共2行。
还要注意结果的索引值没有排序。
最后，看一下使用 join_axes参数的例子：
End of explanation
result = df1.append(df2)
Explanation: 解释：
axis=1，即拼接轴是横轴，先将df1的列和df4的列名进行堆叠，即每一行有7列。由于join_axes=[df1.index]，故结果的索引取值和df1相同，{0,1,2,3}。
使用append()方法进行 行拼接
如果只想对Series或DataFrame对象进行行拼接(axis=0)，推荐使用append()方法。 append()方法实际上就是沿着索引轴(axis=0)进行拼接的concat()。
注意：
如果是对DataFrame对象进行append操作，要注意他们的索引值交集必须为空！即每个DataFrame对象的索引值都不相同。列名不作要求。
其实，对DataFrame进行append操作时是可以忽略索引的，result = df1.append(df4, ignore_index=True)
End of explanation
result = df1.append(df4)
#由于df1和df2的索引值交集不为空，导致最后result的索引值有重复！
Explanation: 
End of explanation
result = df1.append([df2,df3])
Explanation: append()方法可以一次拼接多个对象。
End of explanation
df1
df4
result = pd.concat([df1, df4],ignore_index=True)
result
df1
df4
result2 = pd.concat([df1, df4],axis=1, ignore_index=True) #99.9999%不推荐大家列拼接时使用ignore_index
result2 
Explanation: append()操作并不是直接对df1对象进行操作，而是在df1副本的基础上进行拼接操作。
拼接操作时忽略索引值
大多数情况下，索引值都是默认生成的一些无意义的id，此时，两个DataFrame对象很可能有重复的索引值，但他们并没有实质物理含义，此时，在进行行拼接操作时我们可以忽略索引，使用ignore_index参数即可。
在进行列拼接时，就不要使用ignore_index参数了，因为99.9999%的数据列名都是有意义的。
End of explanation
result = df1.append(df4, ignore_index=True)
Explanation: DataFrame.append方法也有ignore_index参数哦
End of explanation
s1 = pd.Series(['X0','X1','X2','X3','X4'],name='X')
s1
result = pd.concat([df1,s1],axis=1)
result
Explanation: 同时对Series和DataFrame对象进行拼接操作
很简单，原因就是Series会被隐式转为DataFrame对象，同时保持列名相同
End of explanation
s2 = pd.Series(['_0', '_1', '_2', '_3'])
result = pd.concat([df1, s2, s2, s2], axis=1)
Explanation: 如果Series的列没有名字，会默认生成数字用于列名。
End of explanation
s3 = pd.Series([0, 1, 2, 3], name='foo')
s4 = pd.Series([0, 1, 2, 3])
s5 = pd.Series([0, 1, 4, 5])
pd.concat([s3,s4,s5],axis=1)
Explanation: 对Series对象进行拼接时使用keys参数
concat()方法中keys参数除了构建层次化索引外，另一个很常见的使用情景是：对多个Series对象进行拼接操作，我们希望重新制定得到的DataFrame对象中的列名，而不是使用Series中的名字。
End of explanation
pd.concat([s3,s4,s5],axis=1,keys=['red','blue','yellos'])
Explanation: 通过keys参数，来设置生成的DataFrame的列名
End of explanation
result = pd.concat(frames, keys=['x', 'y', 'z'])
Explanation: 回顾一下我们的第一个例子:
End of explanation
pieces = {'x':df1, 'y':df2, 'z':df3}
result = pd.concat(pieces)
result
Explanation: 可以用字典代替上面concat方法中的frames和keys:
End of explanation
result = pd.concat(pieces, keys=['z', 'y']) #只对'z','y'对应的DataFrame进行拼接
result
Explanation: 
End of explanation
s2 = pd.Series(['X0', 'X1', 'X2', 'X3'], index=['A', 'B', 'C', 'D'])
s2
df1
result = df1.append(s2, ignore_index=True) #推荐忽略现有的索引值
result
dicts = [{'A': 1, 'B': 2, 'C': 3, 'X': 4},
        {'A': 5, 'B': 6, 'C': 7, 'Y': 8}]
 
result = df1.append(dicts, ignore_index=True)
Explanation: 对DataFrame对象增加行数
你可以使用append()方法接收一个Series或者列表 对DataFrame对象增加一行，虽然这种方法效率不高,因为要重新生成一个新的DataFrame存放结果。
也可以传递一个Series构成的列表或者字典构成的列表，来增加几行！
End of explanation
left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                     'A': ['A0', 'A1', 'A2', 'A3'],
                     'B': ['B0', 'B1', 'B2', 'B3']
        
    })
right = pd.DataFrame({'key': ['K0', 'K2', 'K1', 'K3'],
                      'C': ['C0', 'C1', 'C2', 'C3'],
                      'D': ['D0', 'D1', 'D2', 'D3']
    })
pd.merge(left, right, on='key')
Explanation: 数据库风格的DataFrame 连接/合并操作
pandas提供了非常高效的DataFrame连接(join)操作，并且使用风格和SQL非常类似。相对于其他的开源实现，pandas无疑是相当高效的, 这要归功于对DataFrame对象的优秀的算法设计和高效的内部数据部署。
如果你之前有过SQL开发经验而首次使用pandas，你可能想先了解二者的对比。
pandas仅提供了一个merge()方法，就能够对DataFrame对象进行类似关系数据库的连接(join)操作，先看merge()参数
merge(left, right, how='inner', on=None, left_on=None, right_on=None,
      left_index=False, right_index=False, sort=True,
      suffixes=('_x', '_y'), copy=True, indicator=False)
left: 参与操作的DataFrame对象
right: 参与操作的另一个DataFrame对象
on: 进行连接操作用到的列名,可以是一列，也可以是多列。这个列名必须在left和right中都存在！ 如果on参数没有赋值，并且left_index和right_index都是False，pandas会将left和right都含有的列作为on的值
left_on: 取left中某一列名作为keys，可以是列名或者长度和DataFrame对象一行长度相等的数组
right_on: 取right中某一列名作为keys, 可以是列名或者长度和DataFrame对象一行长度相等的数组
left_index: 如果取值是True，使用left中的索引作为连接操作的keys
right_index: 意思同上，
how: 取值范围{'left', 'right', 'outer', 'inner'},默认是inner
sort: 是否对结果按照连接keys进行排序，默认是True,如果顺序不重要，可以设置为False，会提高效率
suffixes: 元组。如果left和right中除keys之外，也有列名一样，会用suffixes参数区别, 默认格式('_x', '_y').
copy:是否copy数据，默认为True，这样不会改变left和right
indicator：在pandas 0.17.0中加入的参数，如果设置为True,能够显示结果中的key来自left还是right，
merger方法的返回的对象类型同left。
merge()方法是pandas中的全局方法，你可以通过DataFrame对象调用它。
和merge()方法很相似的是DataFrame.join()方法，它内部使用merge方法来实现 索引与索引、索引与列 的拼接操作，默认是对索引进行拼接，而merge方法默认是对列进行拼接，无疑，对列进行拼接更常见。除非你要对索引进行拼接，通常都是使用merge()方法。
基本的数学知识：关系代数
对数据库操作熟悉的同学肯定对拼接操作不陌生，下面几种情况是必须知道的：
一对一拼接(one-to-one join): 比如对两个DF对象的索引 进行拼接操作，注意此时索引值必须是唯一的
多对一拼接 (many-to-one join): 对一个对象的索引(唯一的)和另一个对象的一列或几列进行拼接操作
多对多拼接 (many-to-many join): 对两个对象的列 进行拼接操作
注意： 显然， 多对多拼接时最常用的，并且在多对多拼接过程中会丢弃索引值。
大家有必要花时间理解多对多拼接操作的情况。在SQL/关系代数中，如果连接时的键值(key)在两个表中值不唯一，拼接结果是两个表的笛卡尔积。
看一个简单的例子来理解笛卡尔积。
End of explanation
left = pd.DataFrame({
        'key1':['K0', 'K0', 'K1', 'K2'],
        'key2':['K0', 'K1', 'K0', 'K1'],
        'A':['A0', 'A1', 'A2', 'A3'],
        'B':['B0', 'B1', 'B2', 'B3']
    })
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
                      'key2': ['K0', 'K0', 'K0', 'K0'],
                       'C': ['C0', 'C1', 'C2', 'C3'],
                       'D': ['D0', 'D1', 'D2', 'D3']})
pd.merge(left, right, on=['key1', 'key2'])
Explanation: 解释:
拼接的键值是'key', left中key这一列的取值是{K0, k1, K2, K3},right中key这一列的取值是{K0, K1, K2, K3}, 由于how参数默认值是'inner', 即内连接，所以笛卡尔积是{K0, K1, K2, K3}
再看一个复杂点的例子, 多个列名作为key
End of explanation
result = pd.merge(left, right, how='left', on=['key1', 'key2'])
Explanation: 解释:
此时拼接操作的键值是['key1', 'key2'],在left中['key1','key2']的取值是{['K0','K0'], ['K0', 'K1'], ['K1', 'K0'], ['K2', 'K1']},在right中['key1',  'key2']的取值是{['K0', 'K0'], ['K1', 'K0'], ['K2', 'K0']}, 默认进行内连接，所以取二者的交集{['K0', 'K0'], ['K1', 'K0']}, 并且left中['K1', 'K0']出现了两次，所以拼接结果是3行。
merge方法中的参数how决定了哪些键值(keys)会被保留到结果中。注意如果on参数接收的键值在left和right中都没有出现，拼接结果是NA。
下面总结了how参数在SQL中对应的操作。
|    参数how取值     | SQL拼接操作  | 操作描述|
| ------------- |:-------------:| :-------------:| 
| left      | LEFT OUTER　JOIN| 只使用来自left中的键值|
| right      | RIGHT OUTER　JOIN      |   只使用来自right中的键值|
| outer | FULL OUTER JOIN      |    使用left、right中键值的并集|
|inner|INNER JOIN|使用left、right中键值的交集|
End of explanation
result = pd.merge(left, right, how='right', on=['key1', 'key2'])
Explanation: 解释：
on的参数是['key1', 'key2'],所以拼接的键值是['key1', 'key2']，how参数是'left',所以进行的是左拼接，只关注left中键值取值。
过程：left中第一行键值是['K0', 'K1'],发现right有此取值，拼接后得到result中的第一行；
left中第二行键值是['K0', 'K1'],发现right中没有此取值，仍进行拼接得到result中第二行，注意'C' 'D'取值NaN
left中第三行键值是['K1', 'K0'], 发现right中有此取值切出现了两次，分别进行拼接得到result中第三行、第四行
left中第四行取值是['K2', 'K1'], 发现right中没有此取值，仍进行拼接得到result中第五行，'C', 'D'取值NaN
End of explanation
result = pd.merge(left, right, how='outer', on=['key1', 'key2'])
Explanation: 
End of explanation
result = pd.merge(left, right, how='inner', on=['key1', 'key2'])
Explanation: 
End of explanation
df1 = pd.DataFrame({'col1':[0,1], 'col_left':['a','b']})
df2 = pd.DataFrame({'col1':[1,2,2],'col_right':[2,2,2]})
df1
df2
pd.merge(df1, df2, on='col1', how='outer', indicator=True)
Explanation: merge方法中indicator参数说明
0.17.0版本才有的参数
merge方法在0.17.0版本中新增了一个参数indicator。这个参数取值True，False或字符串。如果取值True，会在拼接结果中多出一列'_merge', 显示 每一行的键值来自left还是right。
|    _merge值     | 含义|
| ------------- |:-------------:| 
| left_only      | 键值仅来自left|
| right_only      | 键值仅来自right| 
| both | 键值来自left和both|
End of explanation
pd.merge(df1, df2, on='col1', how='outer', indicator='indicator_column')
Explanation: 上面提到indicator参数取值也可以是字符串，没啥特别的，就是在拼接结果中用接收的字符串作为'_merge'的列名罢了。
End of explanation
left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
                       'B': ['B0', 'B1', 'B2']},
                       index=['K0', 'K1', 'K2'])
  
right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
                         'D': ['D0', 'D2', 'D3']},
                         index=['K0', 'K2', 'K3'])
  
result = left.join(right)
Explanation: 对索引进行拼接
DataFrame.join方法的作用是对两个DataFrame对象进行基于索引值的拼接操作。下面是一个简单的例子:
把索引也看做是一列，再来看下面的操作就就没啥了
End of explanation
result = left.join(right, how='outer')
Explanation: 
End of explanation
result = left.join(right, how='inner')
Explanation: 
End of explanation
result = pd.merge(left, right, left_index=True, right_index=True, how='outer')
Explanation: merge方法中提供了left_index, right_index参数同样实现了基于索引的拼接操作。
End of explanation
result = pd.merge(left, right, left_index=True, right_index=True, how='inner')
Explanation: 
End of explanation
left = pd.DataFrame({'k': ['K0', 'K1', 'K2'], 'v': [1, 2, 3]})
right = pd.DataFrame({'k': ['K0', 'K0', 'K3'], 'v': [4, 5, 6]})
result = pd.merge(left, right, on='k')
Explanation: 除拼接键值之外，重复的列名用suffixes参数区别
很多情况下，left和right中除了拼接键值之外，还会有其他列名也相同，为了在结果中加以区分，这个时候suffixes参数就派上用场了。好消息是suffixes有默认值，即使不为它赋值在结果中也能够区分。
举例如下：
End of explanation
result = pd.merge(left, right, on='k', suffixes=['_l', '_r']) #为suffixes参数赋值
Explanation: 默认情况下：
End of explanation
left = left.set_index('k')
right = right.set_index('k')
result = left.join(right, lsuffix='_l', rsuffix='_r')
Explanation: DataFrame.join方法也提供了lsuffix和rsuffix参数来实现同样的功能:
End of explanation
right2 = pd.DataFrame({'v': [7, 8, 9]}, index=['K1', 'K1', 'K2'])
left.join([right, right2])
Explanation: 拼接多个DataFrame对象
DataFrame.join方法能够接收DataFrame对象构成的元组或列表，对列表内所有DF对象进行基于索引的拼接。Panel.join方法也有此功能。
End of explanation
left = pd.DataFrame({'k': ['K0', 'K1', 'K1', 'K2'],
                     'lv': [1, 2, 3, 4],
                     's': ['a', 'b', 'c', 'd']})
right = pd.DataFrame({'k': ['K1', 'K2', 'K4'],
                     'rv': [1, 2, 3]})
left
right
pd.ordered_merge(left, right, fill_method='ffill', left_by='s')
Explanation: 合并 有序数据
v0.18.0新增了一个ordered_merge()方法 对时间序列或者其他有序数据进行合并。并且ordered_merge提供了fill_method参数来填充缺失值。
End of explanation
df1 = pd.DataFrame([[np.nan, 3., 5.], [-4.6, np.nan, np.nan],
                    [np.nan, 7., np.nan]])
df1
df2 = pd.DataFrame([[-42.6, np.nan, -8.2], [-5., 1.6, 4]],
                       index=[1, 2])
df2
Explanation: 使用合并方法填充NaN
End of explanation
df1.combine_first(df2)
df1
Explanation: 先使用combine_first方法：
End of explanation
df1.update(df2)
df1
Explanation: df1和df2列名完全相同，索引值也相似。
由于df2中不存在索引值=0，所以df1中第一行的值原封不动；
对于df1中不等于NaN的值，也不需要改变；
对于df1中等于NaN的值，用df2中同索引同列名的值替换， 得到结果。
注意combine_first()方法不改变df1的值。
如果想改变df1的值，使用update()方法。
End of explanation
<END_TASK>