You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas DataFrame中无需指定行列提取目标子串及数字子串?

问题描述

我有多个Pandas DataFrame,需要提取的目标数据(比如project:后以45开头的4位数字、日期、物质名称)在不同DataFrame中的行列位置完全不固定。目前用df.iloc指定行列拆分的方法适配性极差,操作还繁琐,想找一种不用指定行列就能提取这些子串(尤其是数字子串)的实现方法。

以下是示例DataFrame:

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}}
解决方案

核心思路是用正则表达式替代固定行列定位,通过匹配目标内容的格式规则提取数据,完全不需要指定行列位置。

方法1:全局文本提取(推荐)

把整个DataFrame转换成扁平的文本集合,一次性用正则匹配所有目标内容,效率最高:

import pandas as pd
import re

def extract_targets(df):
    # 将DataFrame所有元素转为字符串,过滤空值后拼接成全局文本
    all_text = ' '.join(str(val) for val in df.stack().dropna())
    
    # 提取project后45开头的4位数字
    project_num = re.search(r'project:\s*(45\d{2})', all_text).group(1)
    # 提取日期(匹配"数字+月份+年份"格式)
    date = re.search(r'date:\s*(\d+\s+\w+\s+\d{4})', all_text).group(1)
    # 提取物质名称
    substance = re.search(r'substance:\s*(\w+)', all_text).group(1)
    
    return {
        'project_number': project_num,
        'date': date,
        'substance': substance
    }

# 测试三个示例DataFrame
for df_name, df in zip(['df', 'df2', 'df3'], [df, df2, df3]):
    result = extract_targets(df)
    print(f"{df_name}提取结果:")
    print(result)

方法2:遍历元素匹配

逐个检查DataFrame的每个元素,找到包含目标关键字的内容后提取,适合需要中途终止遍历的场景:

import pandas as pd
import re

def extract_targets_by_element(df):
    project_num = None
    date = None
    substance = None
    
    # 遍历所有列和行的元素
    for col in df.columns:
        for val in df[col].dropna():
            val_str = str(val)
            # 匹配project字段
            p_match = re.search(r'project:\s*(45\d{2})', val_str)
            if p_match:
                project_num = p_match.group(1)
            # 匹配date字段
            d_match = re.search(r'date:\s*(\d+\s+\w+\s+\d{4})', val_str)
            if d_match:
                date = d_match.group(1)
            # 匹配substance字段
            s_match = re.search(r'substance:\s*(\w+)', val_str)
            if s_match:
                substance = s_match.group(1)
            # 三个目标全部找到后提前终止遍历
            if project_num and date and substance:
                break
        if project_num and date and substance:
            break
    
    return {
        'project_number': project_num,
        'date': date,
        'substance': substance
    }

# 测试
for df_name, df in zip(['df', 'df2', 'df3'], [df, df2, df3]):
    result = extract_targets_by_element(df)
    print(f"{df_name}提取结果:")
    print(result)

关键注意事项

  • 正则规则可以根据实际数据格式调整:比如物质名称包含空格时,把\w+改成[\w\s]+;日期格式变化时,修改日期匹配的正则表达式即可。
  • df.stack()用于将二维DataFrame转为一维序列,简化全局遍历;dropna()过滤空值,避免无效内容干扰匹配。

内容的提问来源于Stack Exchange,提问作者Steve Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 04:01:16