python对比两个dataframe列 pandas比对两个数据集
本教程详细介绍了如何使用Pandas库比较两个DataFrame,识别出它们之间的差异行,并且明显这些差异来源于哪个原始DataFrame。我们将利用pd.merge函数的indicator=True参数来自动生成源标识符,并进一步探讨在合并过程中如何保留并追踪原始DataFrame的行索引,从而实现更精细的数据差异分析。识别DataFrame差异行其来源
在数据分析中,经常需要比较两个结构相似但内容可能存在差异的结合DataFrame,例如比较当前提示与历史提示数据。Pandas提供了强大的合并(merge)功能,特定的参数,可以轻松实现这个目标。
核心方法是使用pd.merge函数,并设置how='outer'和indicator=True。how='outer':执行外连接,这意味着它会保留两个DataFrame中所有不匹配的行,以及匹配的行。indicator=True:这个参数是关键,它会在结果DataFrame中添加一个名为_merge的特殊列。这个列会指示每一行源自哪个原始DataFrame:left_only:该行仅存在于右边DataFrame(合并时形成的第一个DataFrame)。right_only:该行仅存在于右边Data
通过筛选_merge列不为'两者'的行,我们可以得到存在所有差异的行。
示例代码:识别差异行并标注来源
假设我们有两个DataFrame,df_current_est代表当前说明,df_previous_est代表历史说明。
import pandas as pd# 模拟数据df_current_est = pd.DataFrame({ 'EstimateID': [10061, 10062, 10063], '季节': [2023, 2023, 2023], 'RPIN': ['R1000', 'R2000', 'R3000'], 'GrowMethodCode': ['FO', 'FO', 'FO'], 'Variety_code': ['002', '068', '001'], 'Packout_pc': [0.60, 0.76, 0.80], 'QtyBins': [320, 1000, 500]})df_previous_est = pd.DataFrame({ '预估ID': [10061, 10062, 10064], '季节': [2023, 2023, 2023], 'RPIN': ['R1000', 'R2000', 'R4000'], '种植方法代码': ['FO', 'FO', 'FO'], '品种代码': ['002', '068', '003'], 'Packout_pc': [0.60, 0.76, 0.90], 'QtyBins': [9000, 90000, 600]})print(quot;df_current_est:quot;)print(df_current_est)print(quot;\ndf_previous_est:quot;)print(df_previous_est)#执行外连接并添加一次merged_df = pd.merge(df_current_est, df_previous_est, how='outer',indicator=True)#筛选出存在差异的行(即不完全匹配的行)changed_df = merged_df[merged_df['_merge'] != 'both'].copy()#结果打印,_merge列明确指示了行的来源print(quot;\n差异行及其来源:quot;)print(changed_df)登录后复制
解释输出:在上述示例中,changed_df将包含所有在df_current_est和df_previous_est之间不完全匹配的行。_merge列的值(left_only或right_only)明确告诉我们该差异行是来自当前提示或历史提示。例如,如果EstimateID为10061的行在df_current_est中QtyBins为320,而在df_previous_est中QtyBins为9000,那么即使其他列相同,由于QtyBins不同,同时行也被视为差异,并分别显示为left_only和right_only。
注意事项删除:不要_merge列: _merge列是indicator=True参数生成的关键信息,如果将其删除,就无法直接判断行的来源了。定义“差异”:pd.merge默认是基于所有共享列进行匹配。
如果基于部分列进行匹配并查找其他列的差异,需要在参数上明确指定,并在后续处理中比较非列。本教程的例子是基于所有列进行匹配。保留原始DataFrame的行索引
在某些情况下,除了知道差异行来自哪个DataFrame外,我们可能还需要知道这些差异是在原始DataFrame中的具体行索引。_merge列本身不保留原始的行索引信息,因为它生成一个新的DataFrame。为了追踪原始索引,我们需要在合并之前将索引转换为普通列。
示例代码:保留原始索引导入pandas as pd# 模拟数据,携带自定义索引df1 = pd.DataFrame({'key': ['one', 'two', '三'], 'value1': [1, 2, 3]}, index=[101, 102, 103])df2 = pd.DataFrame({'key': ['two', 'four', '三'], 'value2': [20, 40, 30]}, index=[201, 202, 203])print(quot;df1 (带索引):quot;)print(df1)print(quot;\ndf2 (带索引):quot;)print(df2)# 在merge前将索引重置为列,并指定后缀以区分merged_df_with_indices = ( pd.merge(df1.reset_index(), # 将df1的索引转换为'index'列 df2.reset_index(), # 将df2的索引转换为'index'列 on='key', #以'key'为基准进行合并后缀=('_df1', '_df2'), # 为重复列名(包括'index')添加后缀 how='outer',indicator=True))#筛选出差异行changed_df_with_indices = merged_df_with_indices.query('_merge != quot;bothquot;')print(quot;\n其差异行来源和原始索引:quot;)print(changed_df_with_indices)登录后复制
输出解释:在这个例子中:df1.reset_index()将df1的索引(101, 102, 103)转换为一个名为普通列的索引。df2也进行同样的操作。suffixes=('_df1', '_df2')参数在合并时,如果遇到相同名称的非合并键列(如这里的index),会自动添加后缀,生成index_df1和index_df2。最终的changed_df_with_indices不仅包含_merge列指示来源,还包含了index_df1和index_df2列,分别对应差异行在原始df1和df2中的索引。对于left_only的行,index_df2会是NaN;对于right_only的行,index_df1会是NaN。
总结
通过本教程,我们学习了如何利用 pd.merge 函数的how='outer'和indicator=True参数来有效地识别Pandas DataFrame之间的差异行,并清晰地追溯每条差异行的原始来源。我们还探讨了通过在合并前重置索引的方法,来保留并跟踪差异行原始DataFrame中的具体行在索引中,这对于需要回溯数据源的复杂分析场景。另外,掌握这些技巧,将极大地提升您在处理和比较DataFrame数据时的效率和准确性。
以上就是Pandas DataFrame差异识别与来源追溯教程的详细内容,更多请关注乐哥常识网其他相关文章!
