python - 使用字符串匹配慢来切片 Pandas 行

标签 python pandas numpy optimization

我基本上想学习一种基于正则表达式的条件切片来更快地切片 Pandas 数据帧的方法。例如下面的 df(string_column 有 4 个以上的变体,它们仅用于说明目的):

index, string_col1, string_col2, value
0, 'apple', 'this', 10
1, 'pen', 'is', 123
2, 'pineapple', 'sparta', 20
3, 'pen pineapple apple pen', 'this', 234
4, 'apple', 'is', 212
5, 'pen', 'sparta', 50
6, 'pineapple', 'this', 69
7, 'pen pineapple apple pen', 'is',  79
8, 'apple pen', 'sparta again', 78
...
100000, 'pen pineapple apple pen', 'this is sparta', 392

我必须使用正则表达式根据 string_column 进行 bool 条件切片,同时在 value 列中找到具有最小值和最大值的索引,然后最后找到最小值和最大值之间的差异。我通过以下方法执行此操作,但是当我必须匹配许多不同的正则表达式模式时它非常慢:

pat1 = re.compile('apple')
pat2 = re.compile('sparta')
mask = (df['string_col1'].str.contains(pat1)) & (df['string_col2'].str.contains(pat2))
max_idx = df[mask].idxmax()
min_idx = df[mask].idxmin()
difference = df['value'].loc[max_idx] - df['value'].loc[min_idx]

我想得到一个“不同”的答案,我对 df 进行了太多次切片,但我想不出如何减少它。此外,有没有更快的切片方法?

这是一个优化问题,因为我知道我的代码可以满足我的需求。任何提示将不胜感激!

最佳答案

我一直在尝试分析您的示例,但实际上我在合成数据上获得了相当不错的性能,因此我可能需要一些说明。 (此外,出于某种原因,每当我的数据框中有字符串时,.idxmax() 就会中断)。

这是我的测试代码:

import pandas as pd
import re
import numpy as np
import random
import IPython
from timeit import default_timer as timer

possibilities_col1 = ['apple', 'pen', 'pineapple', 'joseph', 'cauliflower']
possibilities_col2 = ['sparta', 'this', 'is', 'again']
entries = 100000
potential_words_col1 = 4
potential_words_col2 = 3
def create_function_col1():
    result = []
    for x in range(random.randint(1, potential_words_col1)):
        result.append(random.choice(possibilities_col1))
    return " ".join(result)

def create_function_col2():
    result = []
    for x in range(random.randint(1, potential_words_col2)):
        result.append(random.choice(possibilities_col2))
    return " ".join(result)

data = {'string_col1': pd.Series([create_function_col1() for _ in range(entries)]),
        'string_col2': pd.Series([create_function_col2() for _ in range(entries)]),
        'value': pd.Series([random.randint(1, 500) for _ in range(entries)])}


df = pd.DataFrame(data)
pat1 = re.compile('apple')
pat2 = re.compile('sparta')
pat3 = re.compile('pineapple')
pat4 = re.compile('this')
#IPython.embed()
start = timer()
mask = df['string_col1'].str.contains(pat1) & \
       df['string_col1'].str.contains(pat3) & \
       df['string_col2'].str.contains(pat2) & \
       df['string_col2'].str.contains(pat4)
valid = df[mask]
max_idx = valid['value'].argmax()
min_idx = valid['value'].argmin()
#max_idx = result['max']
#min_idx = result['min']
difference = df.loc[max_idx, 'value'] - df.loc[min_idx, 'value']
end = timer()
print("Difference: {}".format(difference))
print("# Valid: {}".format(len(valid)))
print("Time Elapsed: {}".format(end-start))

您能解释一下您申请了多少条件吗? (我添加的每个正则表达式只会增加大致线性的时间增加(即 2->3 正则表达式意味着运行时间增加 1.5 倍))。我还对条目数量和两个潜在字符串长度(potential_words 变量)进行了线性缩放。

作为引用,这段代码在我的机器上的计算时间约为 0.15 秒(100 万个条目需要 1.5 秒)。

编辑:我是个白痴,并没有做同样的事情(我正在计算数据集中最小和最大索引值之间的差异,而不是最小值和最大值之间的差异),但是修复它并没有真正增加运行时间。

编辑 2:idxmax() 如何知道在您的示例代码中选择哪一列的最大值?

关于python - 使用字符串匹配慢来切片 Pandas 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45221192/

相关文章:

python - 我如何真正使用 pandas DataFrame 的 `ix` 方法?

python - 如何在伽罗华域上计算 numpy 数组?

python - 尝试超出顶级包的相对导入?

python - 如何将python dict与多处理同步

python - `pandas.DataFrame.to_html()` 没有 `table border` 和 `tr style`

python - python pandas 如何在不同列中找到不重复的值?

Python OpenCV : Rubik's cube solver color extraction

python - 从分层索引 Pandas 的级别删除重复项

python - 具有亚秒级(例如毫秒)分辨率的 to_datetime

python - 在python中求解colebrook(非线性)方程