我们在日常工作中,经常会对两个相似的数据进行对比,想知道两个数据差异在哪儿,如果人眼去观察非常难办,要花很长时间。今天,我们通过这个案例,来看看如何用 Python 中的 pandas 如何高效解决我们的问题。
import pandas as pd
import io
data1 = '''
员工编号 员工姓名
1 张三
2 李四
3 王五
4 小明
5 萧寒
6 大蓝
df1 = pd.read_csv(io.StringIO(data1), sep=r'\s+')
# ...
data2 = '''
员工编号 员工姓名
2 李四
3 王五
5 萧寒
6 大蓝
8 糊涂
12 虚和
15 天天
df2 = pd.read_csv(io.StringIO(data2), sep='\s+')
# ...
以上两个列名相同的数据框,部分行内容相同,部分不同,需要输出二者不同的行。也就是看看前后两期数据,增加和减少了哪些。
我们有三种思路来解决这个需求。
利用 DataFrame 的 align 方法来对齐。由于 align 对齐的是索引的标签,我们将要对比的两列数据转为元组
将两个数据合并,删除相同的数据。(推荐!)
先将两个数据合并,然后按要对比的列分组,然后选择只有一条数据的组即可。
第一个方案。它返回的是由两个 DataFrame 组成的一个元组,其中 为 nan 的行是自己没有的,即:左表为 nan 是右表增加的,右边为 nan 的是右表减少的(相对左表)。
df1.set_index(df1.agg(tuple, axis=1) )
.align(df2.set_index(df2.agg(tuple, axis=1) ))
( 员工编号 员工姓名
(1, 张三) 1.0 张三
(2, 李四) 2.0 李四
(3, 王五) 3.0 王五
(4, 小明) 4.0 小明
(5, 萧寒) 5.0 萧寒
(6, 大蓝) 6.0 大蓝
(8, 糊涂) NaN NaN
(12, 虚和) NaN NaN
(15, 天天) NaN NaN,
员工编号 员工姓名
(1, 张三) NaN NaN
(2, 李四) 2.0 李四
(3, 王五) 3.0 王五
(4, 小明) NaN NaN
(5, 萧寒) 5.0 萧寒
(6, 大蓝) 6.0 大蓝
(8, 糊涂) 8.0 糊涂
(12, 虚和) 12.0 虚和
(15, 天天) 15.0 天天)
第二个思路,索引 df1 的是仅 df1 有的,索引 df2 是 仅 df2 有的。
pd.concat([df1, df2], keys=[*'xy'])
.drop_duplicates(keep=False)
员工编号 员工姓名
df1 0 1 张三
3 4 小明
df2 4 8 糊涂
5 12 虚和
6 15 天天
第三个思路:
pd.concat([df1, df2], keys=['df1', 'df2'])
.groupby(['员工编号', '员工姓名'])
.filter(lambda x: len(x) == 1)
员工编号 员工姓名
df1 0 1 张三
3 4 小明
df2 4 8 糊涂
5 12 虚和
6 15 天天
以上都可以完成需求。
pandas 实战案例集
2024-02-11 21:59:56
pandas align() 数据对齐
2022-05-09 09:57:20
pandas 重复值
2021-07-01 17:46:14
pandas filter() 筛选标签
2022-01-22 14:38:32