PS默认情况下,所有合并函数生成文件的方式均是新生成,即不修改原DF/Series数据。
常用merge()
来添加新字段(即列),concat()
来添加新记录(即行)
++++++++++ merge() ++++++++++
pandas.merge
是pandas的全功能、高性能的的内存连接操作,在习惯上非常类似于SQL之类的关系数据库。base::merge.data.frame
), pandas.merge
的性能要好得多(在某些情况下好得多一个数量级)。其原因是在DataFrame中优化的算法设计和数据的内部布局。DataFrame.merge(
right, # 右DF,即要被merge的DataFrame
how='inner', # 取值有4个{‘left’, ‘right’, ‘outer’, ‘inner’}
on=None, left_on=None, right_on=None, # 如果使用左&右DF的公共字段作为key,使用参数on;如果不使用左边右边的公共字段作为key,使用参数left_on和right_on。
left_index=False, right_index=False, # 如果left_index=True,则left左边DF的index(即索引的列名称)是用来jion的keys。如果是MultiIndex,左DF和右DF的level数必须相等。right_index的作用与之相似。
sort=False, # 默认不对新合并表的结果按照字顺序排序,可以节省运算时间。
suffixes=('_x', '_y'),
copy=True,
indicator=False, # 如果True,会添加一列,显示数据的来源表名称。
Validate=None # 是否检查两个merge的DFkeys是一对一关系、一对多关系,返回布尔值( 'one_to_one'/ '1:1', 'one_to_many' / '1:m', 'many_to_one' / 'm:1')。默认情况下3种关系都可以,只是没有输出。
)
例子
>>> A >>> B
lkey value rkey value
0 foo 1 0 foo 5
1 bar 2 1 bar 6
2 baz 3 2 qux 7
3 foo 4 3 bar 8
>>> A.merge(B, left_on='lkey', right_on='rkey', how='outer')
lkey value_x rkey value_y
0 foo 1 foo 5
1 foo 4 foo 5
2 bar 2 bar 6
3 bar 2 bar 8
4 baz 3 NaN NaN
5 NaN NaN qux 7
A.merge(B, right_on='col_r', left_on='col_l', how='outer').merge(C, right_on='col_r1', left_on='col_l1', how='outer')
注:
- 截止到2019上半年,
merge()
函数仍然会合并左右表的NaN 和 None,详见 GH22491 和GH22618。- 假如要删除NaN 和 None,使用
new_df.dropna(subset=['key_or_keys], inplace=True)
。
"""NaN是float,None是object,虽然都可以在numpy中运行、但是None会把numpy计算性能拉到底,NaN不会。"""
s_bad = pd.Series([1, None], dtype=object)
s_good = pd.Series([1, np.nan])
print(s_bad)
print(s_good)
# 结果如下:
0 1
1 None
dtype: object
0 1.0
1 NaN
dtype: float64
print(s_bad.dropna())
print(s_good.dropna())
# 结果如下
0 1
dtype: object
0 1.0
dtype: float64
print(s_bad.isnull())
print(s_good.isnull())
# 结果如下
0 False
1 True
dtype: bool
0 False
1 True
dtype: bool
++++++++++ concat() ++++++++++
concat()函数一边按照an axis执行所有的复杂合并命令,同时(如果有的话)按其他axes执行运算,还执行参数"join"的设定 innor | outer命令。注意,之所以说“如果有”,是因为Series只有一个axis。
pandas.concat(
objs, # 要纵向合并的DataFrame列表。append也有(4个共同参数)
axis=0, # axis只能取值0或者1
join='outer', # join只能取值innor或outer
sort=None, # append()也有(共4个共同参数),即默认空白。可取值为False/True,从23.0版本开始,不输入取值的话会收到warning提示,之前的版本中默认sort只等于True。
gnore_index=False, # append()也有(共4个共同参数)
# 以下参数不太常用
verify_integrity=False, # append()也有(共4个共同参数)
join_axes=None, keys=None, levels=None, names=None,copy=True)
axis
、join
。 进一步有sort
操作,且未来的join
不再默认执行sort=True
,需要主动设置)、join = innor/outer
操作的是axis(它其实是实际意义上的index,如果你对该函数较熟悉的话)。keys
合并后的表,可以快速的提取数据,key的对象随axis的取值变化而改变。ignore_index
搭配axis
:实现用递增的数字,作为新DF的字段名称;index
换成参数join_axes
可以实现相当于SQL的left join功能,即只保左边表df1的index。例如result = pd.concat([df1, df4], axis=1, join_axes=[df1.index])
。++++++++++ append() ++++++++++
功能:简化版的concat()
(实际上比concat诞生的早)。同样是用来处理Dataframe/Series。
DataFrame.append(
other, # 其他的对象(Series/DF)
sort=None, # 是否排序
ignore_index=False, # 是否使用原index。取值True会用0,1,2……数字作为index
verify_integrity=False)
附注:一个Series合并到一个DataFrame
如果我们要把一个Series合并到一个DataFrame的话,用DataFrame.assign()
可以得到相同的结果。
但是对于任意数量的DataFrame/Series对象,请使用concat()
。
concat()
和append()
通用的:
– 比如2个表的index一个是[i, ii, iii, iv],一个是[a, b, c, d],通过设定ignore_index=True
,即用新的index[0, 1, 2, 3]来添加合并对象。
-仅适用于 concat()
的:
– ignore_index=True
搭配axis=1
(行名称变成了事实上的Column,列名称反而成了事实上的index),可以在合并结果中用数字序号作为列名称;
仅适用于append()
的:
– 直接把一个手写Series 的列 或者一个dict 的列集,合并到DataFrame 行的后边得到一个新的DF。虽然不是特别有效率(因为函数应用的对象Series/DF需要手工码出来)。
— e.g. 手写Series类型数据,手写dict类型数据。其结果不容易理解,一般使用merge
或者concat
:
import pandas as pd
df1 = pd.DataFrame([5, 6, 7, 8], index=['A', 'B', 'C', 'Y'])
print(df1)
s2 = pd.Series(['X0', 'X1', 'X2', 'X3'])
print(s2)
dicts = [{'A': 1, 'B': 2, 'C': 3, 'X': 4},
{'A': 5, 'B': 6, 'C': 7, 'Y': 8}]
print(dicts)
# 结果如下
0
A 5
B 6
C 7
Y 8
0 X0
1 X1
2 X2
3 X3
dtype: object
[{'A': 1, 'B': 2, 'C': 3, 'X': 4}, {'A': 5, 'B': 6, 'C': 7, 'Y': 8}]
result = df1.append(s2, ignore_index=True)
print(result)
b = df1.append(dicts, ignore_index=True)
print(b)
# 结果如下
0 1 2 3
0 5 NaN NaN NaN
1 6 NaN NaN NaN
2 7 NaN NaN NaN
3 8 NaN NaN NaN
4 X0 X1 X2 X3
0 A B C X Y
0 5.0 NaN NaN NaN NaN NaN
1 6.0 NaN NaN NaN NaN NaN
2 7.0 NaN NaN NaN NaN NaN
3 8.0 NaN NaN NaN NaN NaN
4 NaN 1.0 2.0 3.0 4.0 NaN
5 NaN 5.0 6.0 7.0 NaN 8.0
++++++++++ JOIN() ++++++++++
它通过索引或者指定的列把来自其他DaraFrame的列添加到左DF上。
如果只按照索引进行join的话,可以迅速的同时jion多个DataFrame。
DataFrame.join( # 如果第一个参数"other"传入的是"一个列表的DataFrame",参数"on", "lsuffix", "rsuffix"失效。
other, # 要jion的对象,可以是DataFrame、带有名称字段集合的Series、或者一个列表的DataFrame
on=None, # 指明join使用的column(s)。系统默认使用index。
how='left', # 取值有4个{'left', 'right', 'outer', 'inner'}。默认值是'left'。
lsuffix='',
rsuffix='',
sort=False # 默认False,即保留左DF的排序。True则按join的列对生成的DF进行排序
)
例子:
new_df = left.join(right, on=key_or_keys)
new_df = pd.merge(left, right, left_on=key_or_keys, right_index=True, how='left', sort=False)
new_df = left.merge(right, on=key_or_keys, how='left')
pandas.merge()
是所有用来merge/join的底层函数。DataFrame提供了pandas.DataFrame.merge()
和pandas.DataFrame.join()
作为使用pandas.merge()
的快捷方式。
例如df1.merge(right=df2, ...)
,也即pandas.merge(left=df1, right=df2, ...)
。
df.join()
和df.merge()
主要有三处不同df1.join(df2)
默认使用左连接 保留左表df1
的所有行,但是df.merge(df1, df2)
默认使用内连接 保留df1
和df2
共有的行。df1.join(df2)
只能用df2
的index,但是df1.merge(df2)
即可以用df2
的单列/多列,也可以通过right_index=True
使用df2
的index;df1.join(df2, on=key_or_keys)
,df1.merge(df2, left_index=True)
。默认情况,df1.join(df2)
使用df1
的index,同样df1.merge(df2)
用的是df2
的(单列的/多列的)index,;两者都能按照行名称匹配出新的一列。