Python:UserWarning:此模式具有匹配组。要实际获取组,请使用str.extract

时间:2016-10-06 16:47:37

标签: python regex pandas

我有一个数据框,我尝试获取字符串,其中列包含一些字符串 Df看起来像

member_id,event_path,event_time,event_duration
30595,"2016-03-30 12:27:33",yandex.ru/,1
30595,"2016-03-30 12:31:42",yandex.ru/,0
30595,"2016-03-30 12:31:43",yandex.ru/search/?lr=10738&msid=22901.25826.1459330364.89548&text=%D1%84%D0%B8%D0%BB%D1%8C%D0%BC%D1%8B+%D0%BE%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD&suggest_reqid=168542624144922467267026838391360&csg=3381%2C3938%2C2%2C3%2C1%2C0%2C0,0
30595,"2016-03-30 12:31:44",yandex.ru/search/?lr=10738&msid=22901.25826.1459330364.89548&text=%D1%84%D0%B8%D0%BB%D1%8C%D0%BC%D1%8B+%D0%BE%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD&suggest_reqid=168542624144922467267026838391360&csg=3381%2C3938%2C2%2C3%2C1%2C0%2C0,0
30595,"2016-03-30 12:31:45",yandex.ru/search/?lr=10738&msid=22901.25826.1459330364.89548&text=%D1%84%D0%B8%D0%BB%D1%8C%D0%BC%D1%8B+%D0%BE%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD&suggest_reqid=168542624144922467267026838391360&csg=3381%2C3938%2C2%2C3%2C1%2C0%2C0,0
30595,"2016-03-30 12:31:46",yandex.ru/search/?lr=10738&msid=22901.25826.1459330364.89548&text=%D1%84%D0%B8%D0%BB%D1%8C%D0%BC%D1%8B+%D0%BE%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD&suggest_reqid=168542624144922467267026838391360&csg=3381%2C3938%2C2%2C3%2C1%2C0%2C0,0
30595,"2016-03-30 12:31:49",kinogo.co/,1
30595,"2016-03-30 12:32:11",kinogo.co/melodramy/,0

另一个带网址的df

url
003\.ru\/[a-zA-Z0-9-_%$#?.:+=|()]+\/mobilnyj_telefon_bq_phoenix
003\.ru\/[a-zA-Z0-9-_%$#?.:+=|()]+\/mobilnyj_telefon_fly_
003\.ru\/sonyxperia
003\.ru\/[a-zA-Z0-9-_%$#?.:+=|()]+\/mobilnye_telefony_smartfony
003\.ru\/[a-zA-Z0-9-_%$#?.:+=|()]+\/mobilnye_telefony_smartfony\/brands5D5Bbr_23
1click\.ru\/sonyxperia
1click\.ru\/[a-zA-Z0-9-_%$#?.:+=|()]+\/chasy-motorola

我用

urls = pd.read_csv('relevant_url1.csv', error_bad_lines=False)
substr = urls.url.values.tolist()
data = pd.read_csv('data_nts2.csv', error_bad_lines=False, chunksize=50000)
result = pd.DataFrame()
for i, df in enumerate(data):
    res = df[df['event_time'].str.contains('|'.join(substr), regex=True)]

但它会让我回头

UserWarning: This pattern has match groups. To actually get the groups, use str.extract.

我该如何解决?

5 个答案:

答案 0 :(得分:11)

urls中至少有一个正则表达式模式必须使用捕获组。 str.contains仅为df['event_time']中的每一行返回True或False - 它没有使用捕获组。因此,UserWarning会提醒您 正则表达式使用捕获组但未使用匹配。

如果您希望删除UserWarning,您可以找到并从正则表达式中删除捕获组。它们没有显示在您发布的正则表达式模式中,但它们必须存在于您的实际文件中。寻找字符类之外的括号。

或者,您可以通过添加

来禁止此特定的UserWarning
import warnings
warnings.filterwarnings("ignore", 'This pattern has match groups')
在致电str.contains之前

这是一个演示问题(和解决方案)的简单示例:

# import warnings
# warnings.filterwarnings("ignore", 'This pattern has match groups') # uncomment to suppress the UserWarning

import pandas as pd

df = pd.DataFrame({ 'event_time': ['gouda', 'stilton', 'gruyere']})

urls = pd.DataFrame({'url': ['g(.*)']})   # With a capturing group, there is a UserWarning
# urls = pd.DataFrame({'url': ['g.*']})   # Without a capturing group, there is no UserWarning. Uncommenting this line avoids the UserWarning.

substr = urls.url.values.tolist()
df[df['event_time'].str.contains('|'.join(substr), regex=True)]

打印

  script.py:10: UserWarning: This pattern has match groups. To actually get the groups, use str.extract.
  df[df['event_time'].str.contains('|'.join(substr), regex=True)]

从正则表达式模式中删除捕获组:

urls = pd.DataFrame({'url': ['g.*']})   

避免使用UserWarning。

答案 1 :(得分:2)

由于提供了regex=Truesublist被当作正则表达式处理,在您的情况下,该正则表达式包含捕获组(用括号括起来的字符串)。

之所以收到警告,是因为如果您要捕获某些内容,那么将不使用str.contains(根据所提供的模式是否包含在字符串中,该字符串返回布尔值)。

  

很明显,您可以禁止显示警告,但更好可修复   他们。

请转义括号,或者如果您确实想捕获某些内容,请使用str.extract

答案 2 :(得分:2)

您可以改用str.match。在您的代码中:

res = df[df['event_time'].str.match('|'.join(substr), regex=True)]


说明

当正则表达式包含组(例如,正则表达式)时,警告由str.contains触发。在正则表达式r'foo(bar)'中,(bar)部分被视为一个组,因为它在括号中。因此,从理论上讲,您可以从正则表达式中提取出来。

但是, 该警告首先并没有道理 contains应该只能“测试模式或正则表达式中是否包含系列或索引的字符串”(pandas documentation)。与提取组无关。

无论如何,str.match不会发出警告,并且当前与str.contains几乎相同,除了(1)字符串必须完全匹配,以及(2)无法从{停用正则表达式{1}}(str.match有一个str.contains参数可以将其停用)

答案 3 :(得分:1)

您应该使用re.escape(yourString)作为传递给包含的字符串。

答案 4 :(得分:0)

摆脱警告的另一种方法是更改​​正则表达式,使其成为匹配组而不是捕获组。这就是(?:)表示法。

因此,如果匹配的组是(url1|url2),则应将其替换为(?:url1|url2)