应用字典查找功能来比较熊猫数据框列
Posted
技术标签:
【中文标题】应用字典查找功能来比较熊猫数据框列【英文标题】:Apply dictionary look-up function to compare pandas dataframe columns 【发布时间】:2021-11-02 02:21:33 【问题描述】:我想将一个函数应用于 pandas 数据框的两列(A 和 B),以测试它们的每个值是否与字典中的相同结果匹配。我希望它将结果返回到第三列。
我已经尝试了下面的代码和关闭变体,但我不断收到错误,我认为我对数据结构有一些基本的不了解。谁能解释我哪里出错了?我可以想象一些繁琐的替代方法来做到这一点,但我确信一定有一个优雅的解决方案。
def do_they_match(A1,A2):
if A1 in dictionary and A2 in dictionary and dictionary[A1] == dictionary[A2]:
return 1
else:
return 0
df['match'] = df.apply(lambda x: do_they_match(x['A'],x['B']))
## also tried ##
df = df.assign(link=lambda x: do_they_match(x['A'],x['B']))
对于上下文,对于最后一行的替代代码,我得到的错误是 IndexError: ('A', 'occurred at index A')
或 TypeError: 'Series' objects are mutable, thus they cannot be hashed
。数据框列和字典中的值都是字符串。
感谢您的帮助!
【问题讨论】:
你的意思是df['match'] = df.apply(lambda x: do_they_match(x['A'], x['B']), axis=1)
吗?
【参考方案1】:
您收到错误是因为您尝试应用从同一 行 传递数据参数的函数,但使用您的语法,x
in lambda x
指列。因此,代码x['A']
实际上试图将A
作为正在处理的当前列x
的行索引。数据框中的每一列将轮流作为该apply
语句中要处理的列。
您必须使用.apply()
的axis=
参数来指示Pandas 通过传递axis=1
进行逐行操作。
Official document 有axis
参数的解释:
axis 0 or ‘index’, 1 or ‘columns’, default 0 坐标轴 函数应用:
0 或“索引”:将函数应用于每一列。
1 或“列”:将函数应用于每一行。
默认值为axis=0
将函数应用于每个列。
要解决错误,您可以在代码中添加axis=1
:
df['match'] = df.apply(lambda x: do_they_match(x['A'], x['B']), axis=1)
更好的解决方案是您不需要定义自定义函数,可能您可以使用 Pandas 函数.map()
映射字典值,如下所示:
df['match'] = (df['A'].map(dictionary) == df['B'].map(dictionary)).astype(int)
我们使用astype()
将布尔结果转换为整数0
(表示False)和1
(表示True)
例如,我们有以下数据框和dictionary
:
df = pd.DataFrame('A': ['x1', 'x2', 'x3'], 'B': ['y1', 'y2', 'y3'])
A B
0 x1 y1
1 x2 y2
2 x3 y3
dictionary = 'x1': 'apple', 'y1': 'orange', 'x2': 'banana', 'y2': 'banana', 'x3': 'peach'
当我们应用代码时,我们得到:
df['match'] = (df['A'].map(dictionary) == df['B'].map(dictionary)).astype(int)
print(df)
A B match
0 x1 y1 0
1 x2 y2 1
2 x3 y3 0
【讨论】:
你是对的,包括我可以只使用 map 函数更有效地做到这一点。此外,地图函数解决方案在我的数据上运行得更快!谢谢SeaBean! @JamieGorzynski 欢迎您!这是正确的!apply
带自定义功能比较慢。如果可用,请始终寻找要使用的内置 Pandas 功能。仅将.apply
用作最后的手段。以上是关于应用字典查找功能来比较熊猫数据框列的主要内容,如果未能解决你的问题,请参考以下文章