Pandas数据规整之合并
数据合并
Pandas提供了大量方法,能轻松的对Series,DataFrame执行合并操作
- 按行合并
- 追加:append()
- 连接:concat() # 行列均可
- 按列合并
- 复杂合并:merge()
- 按行索引合并:join()
合并重叠数据(一个表为主,先填充再合并):combine_first()
追加 append()
### series s = pd.Series([0, 1], index=['a', 'c']) s1 = pd.Series([2, 3, 4], index=['b', 'd', 'e']) s.append(s1) ### dataframe df = pd.DataFrame(np.random.randn(8, 4), columns = ['A','B','C','D']) s = df.loc[[3, 5]] # 追加合并 df.append(s) df.append(s, ignore_index=True) # 不使用追加表的索引,使用主表的默认索引 ###DataFrame和Series追加合并 # Series的行索引和Dataframe的列索引可以匹配上就可以追加一行,否则 series的行索引充当dataframe的列索引 # 必要参数 ignore_index=True s2 = pd.Series([1,2,3,4], index = ['A','B','C','D']) df.append(s2, ignore_index=True)
连接 .concat()
### 多个表按行或列合并 s1 = pd.Series([0, 1], index=['a', 'c']) s2 = pd.Series([2, 3, 4], index=['b', 'd', 'e']) s3 = pd.Series([5, 6], index=['f', 'g']) # 返回series pd.concat([s1, s2, s3]) # 返回dataframe pd.concat([s1, s2, s3], axis=1, sort=False) # 将 s1 和 s3 沿 0轴 连接创建 s4,这样 s4 和 s1 的 index 是有重复的。 s4 = pd.concat([s1, s3]) # 返回dataframe pd.concat([s1, s4], axis=1, join='outer', sort=False) # 默认outer.并集 pd.concat([s1, s4], axis=1, sort=False, join='inner') # 交集 # 将 n 个 Series 沿 0轴 连接起来,再赋予 n 个 keys 创建多层 Series。 pd.concat([s1, s2, s3], keys=['one', 'two', 'three']) 总结: series key来识别数据源自于哪张表,与ignore_index=True一起用的时候,不在显示keys axis=0时候,直接追加加索引和值返回series axis=1时候,join=outer,series的索引追加到行索引,series的值变为列索引的值,没有为nan,返回Dataframe join=inner,series的索引追加到行索引,series的值变为列索引的值,取交集,返回Dataframe DataFrame axis=0,追加到行,如果columns不同的时候也追加列 axis=1,追加到列,如果行索引相同在相同行索引追加到不同列;行索引不同,追加行索引和列索引
复杂合并 .merge()和.join()
按列合并
merge()函数用于复杂综合数据合并,操作复杂,功能强大
join()是merge()的一个特殊用法,用于按索引合并,操作简单,功能单一
# df1,姓名和分组 df1 = pd.DataFrame({ 'name': ['张三', '李四', '王五', '赵六'], 'group': ['DBA', 'PM','PM', 'HR'] }) # df2,姓名和入职时间 df2 = pd.DataFrame({ 'name': ['李四', '赵六', '张三', '王五'], 'date': [2004, 2008, 2012, 2014] }) 两个表必须有相关性,才有合并的需要 以两个表相关的列(或行索引)为基准,合并 方法1:使用查询和添加列进行表合并,比较麻烦,且行列如不完全对应容易出问题 # 查询添加默认以行索引为基准对齐,所以需要把俩表相关列设为行索引 df11 = df1.set_index('name').copy() df21 = df2.set_index('name').copy() df21['group'] = df11['group'] df21.reset_index() 方法2:合并两个对象,默认匹配相同过的列名,自动对齐合并 要合并的样本量(行数)不同时,合并后的数据会自动扩展,不损失信息 df3 = pd.merge(df1, df2) # df4,每个分组的领导,行数少 df4 = pd.DataFrame({ 'group': ['DBA', 'PM', 'HR'], 'leader': ['钱大', '孙二', '周三'] }) # 样本量(行数)不同时,合并后的数据会自动扩展,不损失信息 pd.merge(df3, df4) df5 = pd.DataFrame({ 'group': ['DBA', 'DBA','PM', 'PM', 'HR', 'HR'], 'skills': ['Linux', '数据库', 'Axuer RP', '社交','招聘', '组织'] }) pd.merge(df1, df5) 两个表没有同名列时,如何合并 两个对象没有同名列时,用left_on和right_on强制指定列名对应合并 # df6,姓名2 username 和薪资 df6 = pd.DataFrame({ 'username': ['王五', '张三', '赵六', '李四'], 'salary': [10000, 160000, 7000, 120000] }) pd.merge(df1, df6, left_on='name', right_on='username') pd.merge(df1, df6, left_on='name', right_on='username').drop('username', axis=1) # 删除重复列
按照行索引合并
当要合并数据的行索引相关时,指定 merge() 函数的参数 left_index 与 right_index 的值为 True,就可以实现自动依照索引序号合并
join()函数也能实现,写法更简单
merge()的优势在于更灵活,尤其是当数据集索引值差别很大,数据合并又必须以其中一组数据的索引值为依据时
# df1a,将df1的name列设为行索引 df2a,将df2的name列设为行索引 df1a = df1.set_index('name') df2a = df2.set_index('name') 按索引合并,最简单的方式 :join() df1a.join(df2a) df1a.join(df2a).reset_index() pd.merge(df1a, df2a, left_index=True, right_index=True) # merge实现,同上 两数据索引差异巨大,又必须以一个索引为主合并 # df1a,姓名和分组,姓名为行索引, df6,姓名2和薪资 # 指定一个表的行索引和另一个表的列为基准合并 pd.merge(df1a, df6, left_index=True, right_on='username') 两个对应列不完全重复的数据集的合并 参数 how how='inner',交集,两个表共有的行 how='outer',并集,两个表所有的行 how='left',表1的行 how='right',表2的行 # df1,姓名和分组 ,df7,姓名和时间,姓名列不完全一致 df7 = pd.DataFrame({'name':['张一', '李二', '赵六'], 'data':[2000,2001,2002]}) pd.merge(df1, df7) pd.merge(df1, df7, how='inner') # 默认,交集 pd.merge(df1, df7, how='outer') # 并集 pd.merge(df1, df7, how='left') # 以左表为基准 pd.merge(df1, df7, how='right') # 以右表为基准 合并数据集中包含两个或以上相同列名时 参数 on 指定用于合并的主键 合并后的数据集中,之前相同的列名会被默认加上 _x 等后缀用于区分 参数 suffixes 可以自定义后缀 # df1,姓名和分组,df8,相同的姓名和分组 df8 = pd.DataFrame({ 'name': ['张三', '王五', '赵六', '李四'], 'group': ['code', 'VP','VP', 'code'] }) pd.merge(df1, df8, on='name') # 通过设置参数 suffixes 自定义后缀 pd.merge(df1, df8, on='name', suffixes=['_L', '_R'])
合并重叠数据(了解)
有一类数据组合问题不能用简单的合并(merge)或连接(concatenation(concat))运算来处理。 如合并全部或部分重叠的两个数据集
举例,我们使用NumPy的where函数,它表示一种等价于面向数组的if-else
以a为基准合并,a的缺失值使用b填充
先给a打补丁(用b填充a的缺失值,再合并)
a = pd.Series([np.nan, 2.5, np.nan, 3.5, 4.5, np.nan], index=['f', 'e', 'd', 'c', 'b', 'a']) b = pd.Series(np.arange(len(a), dtype=np.float64), index=['f', 'e', 'd', 'c', 'b', 'a']) b[-1] = np.nan ax = a.copy() ax.isnull() ax[ax.isnull()] # 查询a的缺失值 ax[ax.isnull()] = b # a的缺失值用b填充(操作默认是索引对齐) Series有一个combine_first方法,实现的也是类似功能, 除了用b填充a的缺失值,还带有pandas数据对齐的合并功能 # :以a2为基准合并,a2缺失数据使用b2填充 a2 = a[2:].copy() b2 = b[:-2].copy() 方法1:使用原生方式打补丁(a2的缺失值使用b2填充) # 1:使用b2填充a2的缺失值(打补丁) a2[a2.isnull()] = b2 # 2:合并数据 a22 = a2.append(b2) # 3:去重,排序 a22.index.duplicated() a22[~(a22.index.duplicated())].sort_index() 方法2:使用combine_first方法,先打补丁,再合并,再去重排序 a3 = a[2:].copy() a3.combine_first(b2) 对于DataFrame,combine_first会在列上应用同样操作,可以将其看做: 用传递对象中的数据为调用对象的缺失数据“打补丁” df11 = pd.DataFrame({'a': [1., np.nan, 5., np.nan], 'b': [np.nan, 2., np.nan, 6.], 'c': range(2, 18, 4)}) df21 = pd.DataFrame({'a': [5., 4., np.nan, 3., 7.], 'b': [np.nan, 3., 4., 6., 8.]}) df11.combine_first(df21) # 以df11为基准,先填充缺失值(用df21的值填充df11),再合并(df21的多余行列合并到df11上) df21.combine_first(df11) # 以df21为基准,先填充(用df11的值填充df21),再合并
本文为原创文章,转载请标明出处