如何在 pandas 中提取另一个词之前的一个词

How to extract a word before another word in pandas

我有这个 pandas DataFrame,它描述了一场足球比赛中的比赛:

play_id type Text
1 pass Jon pass complete to Ben.
2 pass Clock 14:52, Jon pass complete to Mitch.
3 rush Frank rush.

我的 objective 是创建一个名为“passer”的新列,其中包含一个脚本,该脚本将遍历“text”列中的描述,并将采用单词 [= 之前​​的名称34=]。所以我首先使用了这个:

df['passer'] = df['Text'].str.extract(r'(.*?)pass', expand=False).str.strip()

这给了我这个:

play_id type Text passer
1 pass Jon pass complete to Ben. Jon
2 pass Clock 14:52, Jon pass complete to Mitch. Clock 14:52, Jon
3 rush Frank rush. NaN

它适用于第一个和第三个 playid,但不适用于第二个,因为它需要时钟,有时可以包含在描述中。

我尝试在创建我的专栏时实施条件,其中代码检查描述中是否包含 'Clock',并使用正确的正则表达式,但这不起作用:

conditions = [
    (np.where(df.Text.str.contains('Clock', case=False))),
    (np.where(~df.Text.str.contains('Clock', case=False)))
    ]

choices = [
    df['Text'].str.extract(r', (.*?) pass', expand=False).str.strip(), 
    df['Text'].str.extract('(.*?) pass', expand=False).str.strip()
    ]

df['passerNEW'] = np.select(conditions, choices, default='NaN')
df

我收到以下错误:

TypeError: invalid entry 0 in condlist: should be boolean ndarray

有没有办法让这个功能发挥作用?这似乎是一个很好的方法,因为在其他情况下,我可以检查三个不同的条件,以便知道要使用哪个正则表达式。

尝试使用 (?=) 正向前瞻,一种 zero-width assertion。因此,代码将如下所示:

df['passer'] = df['Text'].str.extract(r'(\w+)(?=\spass)', expand=False)

输出:

| play_id  | type  | Text                                     | passer |
| -------- | ----- | ---------------------------------------- | ------ |
| 1        | pass  | Jon pass complete to Ben.                | Jon    |
| 2        | pass  | Clock 14:52, Jon pass complete to Mitch. | Jon    |
| 3        | rush  | Frank rush.                              | NaN    |
  • pandas.Series.str.extract 与正先行条件一起使用。
    • 有关 lookahead 的详尽解释,请参阅 SO: Regex lookahead, lookbehind and atomic groups
    • \s+pass 适用于名称和 'pass' 之间的任意数量的空格(例如 'Jon PaSs'
  • flags=re.IGNORECASE用于忽略'pass'的大小写
      可以使用
    • df.Text.str.lower().str.extract('(\w+(?=\s+pass))') 而不是为标志导入 re
import pandas as pd
import re

# test dataframe
data = {'play_id': ['1', '2', '3'], 'type': ['pass', 'pass', 'rush'], 'Text': ['Jon PASS complete to Ben.', 'Clock 14:52, Jon pass complete to Mitch.', 'Frank rush.']}
df = pd.DataFrame(data)

# display(df)
play_id type                                     Text
      1 pass                Jon PASS complete to Ben.
      2 pass Clock 14:52, Jon pass complete to Mitch.
      3 rush                              Frank rush.

# extract
df['passer'] = df.Text.str.extract('(\w+(?=\s+pass))', flags=re.IGNORECASE)

# display(df)
play_id type                                     Text passer
      1 pass                Jon PASS complete to Ben.    Jon
      2 pass Clock 14:52, Jon pass complete to Mitch.    Jon
      3 rush                              Frank rush.    NaN