将数据框“df1”的字符串列与数据框“df2”的另一个字符串列进行比较,基于哪些其他列进行比较

Posted

技术标签:

【中文标题】将数据框“df1”的字符串列与数据框“df2”的另一个字符串列进行比较,基于哪些其他列进行比较【英文标题】:To compare a String Column of a Dataframe 'df1' with another String Column of a Dataframe 'df2' based on which other columns are compared 【发布时间】: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')

提前致谢!

【问题讨论】:

【参考方案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() 不!这可能会将原始描述更改为,因为我们将它带到结果,这不应该发生。

以上是关于将数据框“df1”的字符串列与数据框“df2”的另一个字符串列进行比较,基于哪些其他列进行比较的主要内容,如果未能解决你的问题,请参考以下文章

熊猫从不同的数据框更新/替换

合并数据框动态

pandas - 合并字符串列不起作用(错误?)

将数据框转换为另一个数据框,将复合字符串单元格拆分为单独的行[重复]

如果元素存在于数据框的另一列中,则删除列表元素

与 pandas 的近似连接