在pandas中,字符串不指定索引,返回一个数字子串

l3zydbqr  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(89)

我有几个字符串的例子,其中我想要提取的文本或数字数据并不总是在同一列或行中,或者实际上在不同字符串的相同顺序中:
df:

{1: {0: 'sample', 1: 2},
 2: {0: 'project: 4568 date: 7 January 2023', 1: 4},
 3: {0: 'substance:water', 1: 6}}

字符串
df2:

{1: {0: 'sample', 1: 2},
 2: {0: 'user ab', 1: 4},
 3: {0: 'project: 4568 date: 7 January 2023', 1: 6},
 4: {0: 'substance:water', 1: 3}}


df3:

{1: {0: nan, 1: 'sample', 2: 2},
 2: {0: 'Monday', 1: 'user ab', 2: 4},
 3: {0: nan, 1: 'project: 4568 substance: water date: 7 January 2023', 2: 6},
 4: {0: nan, 1: 'plate 2', 2: 3}}


我想把“project:”后面的数值(总是以45开头,并且总是4位数),以及这些字符串中的日期和内容提取到它们自己的变量中。
在项目编号的示例中,可以通过以下方式执行此操作:a=df.iloc[0,1].split(' ')[1]获取项目编号,b=df.iloc[0,2].split(':')[1]获取物质名称,但是当数据位于不同的列和行中时,它将成为一个繁琐的练习,并且需要为每个子帧更改拆分的子帧。
有没有一种方法可以从字符串中提取这些数据(子字符串),而不必指定列和行,以及如何从字符串中提取数字子字符串?

xriantvc

xriantvc1#

我会创建一个自定义函数来搜索pd.Series中的字符串值,然后使用正则表达式来找到正确的项。例如:

import re

def find_project_and_date(series):
    for v in series:
        if not isinstance(v, str):
            continue
        project = re.search(r"project:\s*(45\d{2})", v)
        date = re.search(r"date:\s*(.*?\d{4})\b", v)

        if project and date:
            yield project.group(1), date.group(1)

# find first occurrence of `project` and `date`
out = next(m for c in df.columns if (m := next(find_project_and_date(df[c]), None)))
print(out)

字符串
印刷品:

('4568', '7 January 2023')

zynd9foi

zynd9foi2#

一个选项可能是使用stack进行平坦化,然后依赖project/dateextractall信息(关键字之后的所有内容,直到下一个关键字)并转换to_dict

out = (df
       .stack()
       .str.extractall(r'\b(project|date): *((?:[^:](?!\w+:))+)')
       .set_index(0)[1].to_dict()
       )

字符串

  • 注意。这是假设每个框架只有一个匹配,如果你可以有几个,很容易处理它们,但你必须澄清如何。

输出量:

{'project': '4568', 'date': '7 January 2023'}


regex demo

相关问题