将数据框“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 【问题描述】:输入解释:
我有两个数据框df1
和df2
,其中包含如下所述的列。
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
【讨论】:
更新了上面的代码以处理大小写混合,例如AAA
或AaA
不!这可能会将原始描述更改为,因为我们将它带到结果,这不应该发生。
更新了代码以将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”的另一个字符串列进行比较,基于哪些其他列进行比较的主要内容,如果未能解决你的问题,请参考以下文章