Pandas 将文本切片到新列,开始和结束位置由正则表达式表示

Pandas slice text to new column with start stop location denoted by regular expression

感谢您帮助解决这个问题。我还是 python 的新手,但知道 VBA excel。

在正则表达式条件下将开始和停止位置提取到数据框中的新列时,返回整数并且没有问题。但是当尝试使用该代码对文本进行切片时,出现以下错误

TypeError: 切片索引必须是整数或 None 或具有 index 方法

我有以下数据框数据行和代码行,这是我在过去几天尝试了许多不同的变体后尝试过的。我觉得这是我最接近解决它的一次。

|MENU_HINT                         |StartPos  |EndPos 
|AUS / Maitland (AUS) 28th Feb     |4         |22      
df2['StartPos'] = df2["MENU_HINT"].str.find('/')

df2['EndPos'] = df2["MENU_HINT"].apply(lambda x: re.search('d+', x).start() if re.search('\d+', x) else re.search('\d+', x)) + 1

df2['Track'] = df2['MENU_HINT'].apply(lambda x: x[x.find('/ ') + 1:df2['EndPos']])

我希望提取从“/”开始的位置名称,并将日期排除到 MENU_HINT 列的新列中。

我什至尝试了下面的代码,我发现它也以整数形式提供了结束位置。但是,当尝试使用列或自己为切片编码时,它仍然会提供相同的错误

df2['Track3'] = df2["MENU_HINT"].apply(lambda x: re.search(
    '\d+', x).start() if re.search('\d+', x) else re.search('\d+', x)) + 1

我正在尝试查找第一个数字,因为该字段只有一个我想截断的日期。

我仍处于学习模式,但可以很好地理解概念,所以我想了解为什么会发生这种情况,因为它对我来说似乎是一个有用的知识库,因为我会遇到这种类型的提取经常。

感谢您花时间和精力帮助我解决这个问题。

真诚的, 保罗

这一行的问题:

df2['Track'] = df2['MENU_HINT'].apply(lambda x: x[x.find('/ ') + 1:df2['EndPos']])

是您将函数应用于列 MENU_HINT,哪些行将在 lambda 函数中称为 x,然后在函数内部获取 df2['EndPos'],这将return a 整列不只是一个整数,因此不能用于索引。要对此进行编辑,您可以将该函数应用于行,如下所示:

df['Track3'] = df.apply(lambda x: x["MENU_HINT"][x["MENU_HINT"].find('/ ') + 1:x['EndPos']], axis=1)

请注意,我将 axis=1 传递给 apply 函数,这会将函数应用于 DataFrame 的整行,让我可以访问其中的任何一行。

另一种方法是直接使用正则表达式来提取您想要的部分,如下所示:

df['Track3'] = df["MENU_HINT"].apply(lambda x:re.search(r"[A-Za-z]+ / ([A-Za-z | ( | )]+)", x).group(1))

在这里,我要搜索以字母字符开头,后跟斜杠,然后再是字母字符或圆括号的字符串。其输出如下所示:

        MENU_HINT                           Track
   AUS / Maitland (AUS) 28th Feb    Maitland (AUS)
   

如果您希望使函数长于一行(因为 lambda 函数在某些情况下会有所限制),这将使对字符串的操作更加清晰和注释,那么您可以这样做:

import pandas as pd

# sample data for dataframe
d = {'menu_hint':['AUS / Maitland (AUS) 28th Feb']}

df = pd.DataFrame(d)

print('the old dataframe:')
print(df)

def strip_word(s:str):
    ''' function to strip parts of word '''

    # n is the start position
    n = s.find('/')
    n = n+2 # adjust for spaces

    # m is the end position
    m = s.find(') ')
    m = m+1 # adjust for zero index

    s_new = s[n:m]

    return s_new 



df['Track3'] = df['menu_hint'].apply(strip_word)

print('the new dataframe:')
print(df)

输出:

                       menu_hint
0  AUS / Maitland (AUS) 28th Feb
the new dataframe:
                       menu_hint          Track3
0  AUS / Maitland (AUS) 28th Feb  Maitland (AUS)