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

基于字符位置与长度提取RAW列结构化数据的技术咨询

数据解析需求:从RAW列提取指定字段到单独列

问题背景

我有一个包含RAW列的文件,数据示例如下:

STARTNA03N010110FIRST_NAME0211MIDDLE_NAME0309LAST_NAME0501S060829041987070110803PHL090101001M.....END

解析规则

  • 从START后提取姓名段,段标识符为NA03N01
  • 字段格式为XXYY:XX是字段标识符,YY是值的字符长度,后续对应长度的字符串为字段值
    • 01XX:名字(FNAME),必填
    • 02XX:中间名(MNAME),非必填
    • 03XX:姓氏(LNAME),必填
    • 04XX:母亲姓氏,非必填
    • 05XX:婚姻状况(CIVIL_STATUS),示例中0501S代表婚姻状况为S(单身)
  • 姓名段后还有其他可变结构的段,如ID段(ID03I01)、地址段(PA03A01)等,各段因非必填字段存在结构差异

现有尝试代码

我尝试基于段生成列,代码如下:

rows_2d = ["NA03N", "ID03I", "PA03A","EA03E"]

all_codes = []

for code in rows_2d:
    for i in range(20):
        all_codes.append(code + ("{0:0=2d}".format(i+1)))

整数校验函数:

def isInt(s):
    try:
        int(s)
        return True
    except ValueError:
        return False

提取值的方法:

def get_next_characters_w_columns(code, string, columns):
    
    done = 0
    output = ""
    
    code_index = string.find(code)
    
    if code_index == -1:
        return "None"
    
    a = code_index + len(code)
    while(done < len(columns)):   
        if isInt(string[a:a+2]):
            fieldNo = int(string[a:a+2])
            temp_output = string[a+4:a+4+int(string[a+2:a+4])]
            a = a + int(string[a+2:a+4]) + 4
            
            if fieldNo in columns:
                output = output + temp_output
                done += 1
                if done < len(columns):
                    output = output + " "
                
            if fieldNo > max(columns):
                return output
        else:
            return output
    return output

调用方法:

def get_info(row, code, place=[i+1 for i in range(35)]):
    if "START" in row["RAW"]:
        info = get_next_characters_w_columns(code, row["RAW"], place)
        if (info == "-1") or (info == "-5"):
            return "No Info"
        else:
            return info
    else:
        return "None"

真实需求

直接从RAW列提取对应值并放入单独列(如FNAME、MNAME、LNAME等),而非先生成段再提取,避免非必填字段带来的额外处理难度。


解决方案

思路

直接定位姓名段起始位置,逐个解析字段,直到遇到其他段的标识符(如ID03I、PA03A等)为止,将每个字段值映射到对应的列,无需提前处理所有段结构。

实现代码

import pandas as pd

# 定义字段标识符与目标列名的映射
FIELD_MAP = {
    "01": "FNAME",
    "02": "MNAME",
    "03": "LNAME",
    "04": "MOTHER_LNAME",
    "05": "CIVIL_STATUS"
}

# 定义其他段的起始前缀,用于终止姓名段解析
OTHER_SEGMENT_PREFIXES = {"ID03I", "PA03A", "EA03E"}

def parse_raw_row(raw_str):
    # 初始化结果字典,所有字段默认值为None
    result = {col: None for col in FIELD_MAP.values()}
    
    # 定位START标记
    start_idx = raw_str.find("START")
    if start_idx == -1:
        return result
    
    # 定位姓名段起始位置
    name_segment_start = raw_str.find("NA03N01", start_idx)
    if name_segment_start == -1:
        return result
    
    current_pos = name_segment_start + len("NA03N01")
    str_length = len(raw_str)
    
    while current_pos + 4 <= str_length:
        # 检查是否进入其他段,是则停止解析
        for prefix in OTHER_SEGMENT_PREFIXES:
            if raw_str.startswith(prefix, current_pos):
                return result
        
        field_id = raw_str[current_pos:current_pos+2]
        # 处理非目标字段:跳过该字段
        if field_id not in FIELD_MAP:
            try:
                length = int(raw_str[current_pos+2:current_pos+4])
                current_pos += 4 + length
            except ValueError:
                return result
            continue
        
        # 解析目标字段
        try:
            length = int(raw_str[current_pos+2:current_pos+4])
            field_value = raw_str[current_pos+4:current_pos+4+length]
            result[FIELD_MAP[field_id]] = field_value
            # 移动指针到下一个字段
            current_pos += 4 + length
        except ValueError:
            # 解析失败则终止
            return result
    
    return result

# 示例使用:假设df是包含RAW列的DataFrame
df = pd.DataFrame({
    "RAW": ["STARTNA03N010110FIRST_NAME0211MIDDLE_NAME0309LAST_NAME0501S060829041987070110803PHL090101001MEND",
            "STARTNA03N010108JOHN_DOE0307SMITH0501MID03I01...END"]
})

# 应用解析函数并合并到原DataFrame
parsed_data = df["RAW"].apply(parse_raw_row).apply(pd.Series)
df = pd.concat([df, parsed_data], axis=1)

# 查看结果
print(df[["RAW", "FNAME", "MNAME", "LNAME", "CIVIL_STATUS"]])

代码说明

  1. FIELD_MAP:统一管理字段标识符和目标列名的对应关系,便于后续维护
  2. OTHER_SEGMENT_PREFIXES:标记其他段的起始前缀,确保姓名段解析不会越界
  3. parse_raw_row函数:
    • 先定位START和姓名段的起始位置,未找到则返回空结果
    • 逐个解析字段:遇到其他段则停止,非目标字段直接跳过,目标字段解析值后存入结果字典
    • 加入异常处理,避免因数据格式错误导致程序崩溃
  4. DataFrame应用:通过apply将解析逻辑批量应用到每一行,再将结果展开为列合并到原表,直接生成FNAME、MNAME等单独列

该方案精准适配非必填字段的可变结构场景,无需先处理所有段,直接提取目标字段到对应列。


内容的提问来源于stack exchange,提问作者aldrean

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 09:30:49