Pandas数据规整之合并

数据合并

Pandas提供了大量方法,能轻松的对Series,DataFrame执行合并操作

  • 按行合并
  1. 追加:append()
  2. 连接:concat() # 行列均可
  • 按列合并
  1. 复杂合并:merge()
  2. 按行索引合并: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),再合并

  

  

  

本文为原创文章,转载请标明出处
原文地址:https://www.cnblogs.com/harden13/p/13528001.html