切片与字符串匹配缓慢的熊猫行

我基本上想学习一种更快速的方法来基于正则表达式切分一个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进行布尔条件切片,同时在值列中查找具有最小值和最大值的索引,然后最终找到最小值和最大值之间的差值。 我用下面的方法做到这一点,但是当我必须匹配许多不同的正则表达式模式时,它是超慢的:

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,但我无法弄清楚如何少做。 此外,还有更快的方法来切片吗?

这是一个优化问题,因为我知道我的代码使我获得了我所需要的。 任何提示将不胜感激!


您可以通过不使用&而是使用scipy.logical_and()来加快逻辑比较50倍

a = pd.Series(sp.rand(10000) > 0.5)
b = pd.Series(sp.rand(10000) > 0.5)

%timeit sp.logical_and(a.values,b.values)
100000 loops, best of 3: 6.31 µs per loop

%timeit a & b
1000 loops, best of 3: 390 µs per loop

我一直在试图描述你的例子,但实际上我的综合数据表现非常出色,所以我可能需要一些澄清。 (另外,出于某种原因,每当我在我的数据框中有一个字符串时,.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变量)进行了线性缩放。

作为参考,此代码在我的机器上以~15秒为单位进行评估(100万条记录需要大约1.5秒)。

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

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


将每个掩码传递给数据帧的下一个子集,每个新的过滤发生在原始数据帧的较小子集上:

pat1 = re.compile('apple')
pat2 = re.compile('sparta')
mask1 = df['string_col1'].str.contains(pat1)
mask = (df[mask1]['string_col2'].str.contains(pat2))
df1=df[mask1][mask]
max_idx = df1['value'].idxmax()
min_idx = df1['value'].idxmin()
a,b=df1['value'].loc[max_idx],df1['value'].loc[min_idx]
链接地址: http://www.djcxy.com/p/96845.html

上一篇: Slicing Pandas rows with string match slow

下一篇: Syntax Error in Angular App: Unexpected token <