如何在Python Pandas中对两个非数值型DataFrame执行差集运算
如何计算两个同列DataFrame的差集(A - B)
你需要的是仅存在于df1(A)中、不存在于df2(B)中的行,也就是df1减去两者的交集。这里有几种实用的方法,结合你的示例代码来演示:
首先先补全示例数据,让演示更清晰:
import pandas as pd # 初始化df1 df1 = pd.DataFrame(columns=['A','B','C']) df1 = df1.append({'A': 'bmw','B':'three','C':'series'}, ignore_index=True) df1 = df1.append({'A': 'merc','B':'S','C':'class'}, ignore_index=True) df1 = df1.append({'A': 'Audi','B':'A','C':'4'}, ignore_index=True) # 补全你未写完的行 # 初始化df2,包含和df1的交集行,以及新行 df2 = pd.DataFrame(columns=['A','B','C']) df2 = df2.append({'A': 'bmw','B':'three','C':'series'}, ignore_index=True) df2 = df2.append({'A': 'toyota','B':'Camry','C':'XLE'}, ignore_index=True)
方法1:使用merge的indicator参数(推荐)
这是最直观且处理边缘情况(比如缺失值)更友好的方法:
# 以左连接合并两个DataFrame,添加_merge列标记行的来源 merged_df = df1.merge(df2, on=['A', 'B', 'C'], how='left', indicator=True) # 筛选出仅存在于df1的行,然后移除_merge列 df_diff = merged_df[merged_df['_merge'] == 'left_only'].drop('_merge', axis=1) print(df_diff)
输出结果:
A B C 1 merc S class 2 Audi A 4
原理:how='left'会保留df1的所有行,indicator=True会生成一个_merge列,值为left_only(仅在df1)、right_only(仅在df2)或both(同时存在于两者)。我们只需要筛选left_only的行即可。
方法2:利用集合的差集操作
如果你喜欢更简洁的集合运算,可以把每行转换成元组后计算差集:
# 将df1和df2的行转换为不含索引的元组集合 df1_rows = set(df1.itertuples(index=False, name=None)) df2_rows = set(df2.itertuples(index=False, name=None)) # 计算差集,再转换回DataFrame diff_rows = df1_rows - df2_rows df_diff = pd.DataFrame(diff_rows, columns=df1.columns) print(df_diff)
输出结果和方法1一致(注意:集合是无序的,所以行的顺序可能和原df1不同,如果需要保持顺序,可以结合原df1的索引做二次筛选)。
⚠️ 注意:如果你的DataFrame中包含NaN值,这种方法可能会出错,因为NaN在集合中不会被视为相等(NaN != NaN),此时方法1会更可靠。
方法3:使用concat和drop_duplicates
这种方法通过标记来源后去重实现:
# 给两个DataFrame添加来源标记列 df1['source'] = 'df1' df2['source'] = 'df2' # 合并两个DataFrame combined = pd.concat([df1, df2]) # 移除在两个DataFrame中都存在的行(即重复行) unique_rows = combined.drop_duplicates(subset=['A', 'B', 'C'], keep=False) # 筛选出仅来自df1的行,移除source列 df_diff = unique_rows[unique_rows['source'] == 'df1'].drop('source', axis=1) print(df_diff)
这个方法同样能得到正确结果,但需要额外添加和移除标记列,相对前两种稍显繁琐。
内容的提问来源于stack exchange,提问作者Jeremy Hunts
相关产品推荐
相关产品推荐

