【问题标题】:To compare a String Column of a Dataframe 'df1' with another String Column of a Dataframe 'df2' based on which other columns are compared将数据框“df1”的字符串列与数据框“df2”的另一个字符串列进行比较,基于哪些其他列进行比较
【发布时间】:2020-10-21 19:58:45
【问题描述】:

输入解释: 我有两个数据框df1df2,其中包含如下所述的列。

df1

Description   Col1    Col2
AAA           1.2     2.5
BBB           1.3     2.0
CCC           1.1     2.3

df2

Description   Col1    Col2
AAA           1.2     1.3
BBB           1.3     2.0

场景: 必须比较df1['Description']df2['Description'],当两者都相等时,必须将df1['Col1']df2['Col1']df1['Col2']df2['Col2'] 进行比较,并产生如下预期的结果。

预期输出:

Description    Col1    Col2   Col1_Result           Col2_Result
AAA            1.2     2.5    Pass                  Fail
BBB            1.3     2.0    Pass                  Pass
CCC            1.1     2.3    Not found in df2      Not found in df2

试用过的代码: 已针对上述场景尝试了下面提到的代码行,但不起作用。通过错误“ValueError:只能比较相同标签的系列对象”

df1['Col1_Result'] = np.where(df1['Description']== df2['Description'],np.where(df1['Col1'] == df2['Col1'], 'Pass', 'Fail'),'Not found in df2')
df1['Col2_Result'] = np.where(df1['Description']== df2['Description'],np.where(df1['Col2'] == df2['Col2'], 'Pass', 'Fail'),'Not found in df2')

提前致谢!

【问题讨论】:

    标签: python pandas string numpy dataframe


    【解决方案1】:

    或者,下面的代码适用于给定的示例。如果有边缘情况,可以根据需要进行修改。

    # Import libraries
    import pandas as pd
    
    # Create DataFrame
    df1 = pd.DataFrame({
        'Description':['AaA', 'BBB','CCC'],
        'Col1': [1.2,1.3,1.1],
        'Col2':[2.5,2.0,2.3]
    })
    df2 = pd.DataFrame({
        'Description': ['AAA', 'BBB'],
        'Col1': [1.2, 1.3],
        'Col2': [1.3, 2.0]
    })
    
    # Convert to lower case
    df1['Description'] = df1['Description'].str.lower()
    df2['Description'] = df2['Description'].str.lower()
    
    # Merge df
    df = df1.merge(df2, on='Description', how='left')
    
    
    # Compare
    df['Col1_result'] = df.apply(lambda x: 'Not found in df2' if (pd.isna(x['Col1_y'])) else
                                            'Pass' if x['Col1_x']==x['Col1_y'] else
                                            'Fail', axis=1)
    df['Col2_result'] = df.apply(lambda x: 'Not found in df2' if (pd.isna(x['Col2_y'])) else
                                            'Pass' if x['Col2_x']==x['Col2_y'] else
                                            'Fail', axis=1)
    
    # Keep only columns from df1
    df = df.drop(['Col1_y', 'Col2_y'], axis=1)
    # Remove '_x' from column names
    df.columns = df.columns.str.replace(r'_x$', '')
    
    # Change to upper case
    df['Description'] = df['Description'].str.upper()
    

    输出

    df
    
      Description  Col1  Col2       Col1_result       Col2_result
    0         AAA   1.2   2.5              Pass              Fail
    1         BBB   1.3   2.0              Pass              Pass
    2         CCC   1.1   2.3  Not found in df2  Not found in df2
    

    【讨论】:

    • 更新了上面的代码以处理大小写混合,例如AAAAaA
    • 不!这可能会将原始描述更改为,因为我们将它带到结果,这不应该发生。
    • 更新了代码以将Description 的大小写更改为大写,即现在与原始代码相同。
    • 如果 String 是 'Aa',这不起作用,因为最后它可能会将整个字符串更改为大写。无论如何谢谢你的帮助伙伴!找到解决方案。
    【解决方案2】:

    使用DataFrame.merge 与左连接输出DataFrame,然后通过DataFrame.filter 选择添加的列,并通过首先比较缺失值的值然后在numpy.select 中相互比较来创建输出:

    df1['desc'] = df1['Description'].str.lower() 
    df2['desc'] = df2['Description'].str.lower()
    df = (df1.merge(df2, on='desc', suffixes=['', '_Result'], how='left')
             .drop(['Description_Result','desc'], axis=1))
    
    df3 = df.filter(like='_Result')
    new = df3.rename(columns=lambda x: x.replace('_Result',''))
    
    df[df3.columns] = np.select([new.isna(), 
                                 df[new.columns].eq(new)], 
                                ['Not found in df2', 'Pass'], 'Fail')
    print (df)
      Description  Col1  Col2       Col1_Result       Col2_Result
    0         AAA   1.2   2.5              Pass              Fail
    1         BBB   1.3   2.0              Pass              Pass
    2         CCC   1.1   2.3  Not found in df2  Not found in df2
    

    详情

    print (df3)
       Col1_Result  Col2_Result
    0          1.2          1.3
    1          1.3          2.0
    2          NaN          NaN
    
    print (new)
       Col1  Col2
    0   1.2   1.3
    1   1.3   2.0
    2   NaN   NaN
    

    【讨论】:

    • 感谢您的解决方案,效果很好!但是,比较不应该区分大小写。在这里,当 df1['Col1']='Ddd' 和 df2['Col1']='DDD' 条件判断结果为“在 df2 中未找到”。这不应该是这样。结果应该是“通过”。有什么可能的方法吗?!
    • @SaranyaSubramanien - 谢谢,将 df[new.columns].eq(new) 更改为 df[new.columns].astype(str).str.lower().eq(new.astype(str).str.lower())
    • 糟糕!我的意思是 df1['Description']='Ddd' 和 df2['Description']='DDD' ,所以 'Col1_Result' 和 'Col2_Result' assings 'NaN' 反过来我们到达“在 df2 中找不到”
    • @SaranyaSubramanien - 然后在我的解决方案之前使用df1['Description'] = df1['Description'].str.lower() df2['Description'] = df2['Description'].str.lower()
    • 不!这可能会将原始描述更改为,因为我们将它带到结果,这不应该发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2022-06-14
    • 2015-04-04
    • 2020-05-31
    • 2021-08-27
    相关资源
    最近更新 更多