首页 > 解决方案 > 如何在熊猫数据框中执行排序搜索?

问题描述

我有一个如下所示的输入字符串:

ms = 'hello stack overflow friends'

以及具有以下结构的熊猫数据框:

      string  priority  value
0         hi         1      2
1  astronaut        10      3
2   overflow         3     -1
3     varfoo         4      1
4      hello         2      0

然后我正在尝试执行以下简单算法:

  1. 按列对 pandas 数据帧进行升序排序df['priority']
  2. 检查ms字符串变量是否包含该df['string']单词。
  3. 如果是,则返回其df['value'].

因此,这是我这样做的方法:

import pandas as pd

ms = 'hello stack overflow friends'

df = pd.DataFrame({'string': ['hi', 'astronaut', 'overflow', 'varfoo', 'hello'],
                   'priority': [1, 10, 3, 4, 2],
                   'value': [2, 3, -1, 1, 0]})

final_val = None

for _, row in df.sort_values('priority').iterrows():
    # just printing the current row for debug purposes
    print (row['string'], row['priority'], row['value'])

    if ms.find(row['string']) > -1:
        final_val = row['value']
        break

print()
print("The final value for '", ms, "' is ", final_val)

它返回以下内容:

hi 1 2
hello 2 0

The final value for ' hello stack overflow friends ' is  0

这段代码工作正常,但问题是我的 df 有 20K 行,我需要执行这种搜索超过 1K 次。

这大大降低了我的流程的性能。那么有没有比我使用纯熊猫更好(或更简单)的方法并避免不必要的循环?

标签: pythonpandasdataframe

解决方案


编写一个可以应用于数据框而不是使用的函数iterrows

match_set = set(ms.split())
def check_matches(row):
    return row['value'] if row['string'] in match_set else None

df['matched'] = df.apply(check_matches, axis=1)

这给了你:

   priority     string  value  matched
0         1         hi      2      NaN
1        10  astronaut      3      NaN
2         3   overflow     -1     -1.0
3         4     varfoo      1      NaN
4         2      hello      0      0.0

然后您可以对值进行排序并从中获取第一个非NaNdf.matched以获取您所调用的内容final_value

df.sort_values('priority').matched.dropna().iloc[0]
0.0

或者,您可以对 df 进行排序并将其转换为元组列表:

l = df.sort_values('priority').apply(lambda r: (r['string'], r['value']), axis=1).tolist()

给予:

l
[('hi', 2), ('hello', 0), ('overflow', -1), ('varfoo', 1), ('astronaut', 3)]

并编写一个在第一次匹配时停止的函数:

def check_matches(l):
    for (k, v) in l:
        if k in match_set:
            return v
check_matches(l)
0

推荐阅读