基于条件自动填充Pandas DataFrame中空缺的section_id
Pandas DataFrame章节ID空值填充方案
原始数据
import pandas as pd data = { 'sec_id': ['1', '', '1.2', '1.3', '1.3.1', '1.3.2', '2', '2.1', '2.2', '2.3', '', '2.3.2', '2.3.3', '3', '4', '4.1', '4.1.1', '4.2', '4.3', '4.4', '5', '5.1', '5.2', '5.3', '5.3.1', '5.3.2', '5.3.3', '5.3.4', '5.3.5', '5.4', '5.5', '6', '6.1', '6.1.1', '6.2', '6.3', '6.4', '6.5', '6.6', '6.6.1', '6.6.2', '6.6.3', '6.7', '6.8', '6.9', '6.9.1', '', '', '6.9.2'], 'p_type': ['Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading1', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading4', 'Heading4', 'Heading3'] } df = pd.DataFrame(data)
填充规则
- 章节ID层级数由
p_type决定:HeadingN对应N级ID(如Heading3对应3个分隔点、4位数字的格式,例如1.2.3.1) - 空值需基于前序有效章节ID和当前段落类型递增生成:例如第11行(索引10)空值生成
2.3.1,第47、48行(索引46、47)空值分别生成6.9.1.1和6.9.1.2 - 最多支持10级子章节
预期输出
sec_id = [ '1', '1.1', '1.2', '1.3', '1.3.1', '1.3.2', '2', '2.1', '2.2', '2.3', '2.3.1', '2.3.2', '2.3.3', '3', '4', '4.1', '4.1.1', '4.2', '4.3', '4.4', '5', '5.1', '5.2', '5.3', '5.3.1', '5.3.2', '5.3.3', '5.3.4', '5.3.5', '5.4', '5.5', '6', '6.1', '6.1.1', '6.2', '6.3', '6.4', '6.5', '6.6', '6.6.1', '6.6.2', '6.6.3', '6.7', '6.8', '6.9', '6.9.1', '6.9.1.1', '6.9.1.2', '6.9.2' ] p_type = [ 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading1', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading4', 'Heading4', 'Heading3' ]
尝试的错误代码
current_section_id = "" current_level = 0 for index, row in df.iterrows(): if row['sec_id'] == '': current_level += 1 section_id = current_section_id.split('.') section_id[current_level - 1] = str(int(section_id[current_level - 1]) + 1) section_id = '.'.join(section_id[:current_level]) current_section_id = section_id df.at[index, 'document_section_id'] = section_id else: current_section_id = row['sec_id'] current_level = row['paragraph_type'].count('Heading') - 1
正确实现方案
核心思路是用一个列表跟踪每一级章节的当前编号,根据p_type确定当前层级,针对空值/非空值分别更新编号并生成章节ID:
import pandas as pd data = { 'sec_id': ['1', '', '1.2', '1.3', '1.3.1', '1.3.2', '2', '2.1', '2.2', '2.3', '', '2.3.2', '2.3.3', '3', '4', '4.1', '4.1.1', '4.2', '4.3', '4.4', '5', '5.1', '5.2', '5.3', '5.3.1', '5.3.2', '5.3.3', '5.3.4', '5.3.5', '5.4', '5.5', '6', '6.1', '6.1.1', '6.2', '6.3', '6.4', '6.5', '6.6', '6.6.1', '6.6.2', '6.6.3', '6.7', '6.8', '6.9', '6.9.1', '', '', '6.9.2'], 'p_type': ['Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading1', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading4', 'Heading4', 'Heading3'] } df = pd.DataFrame(data) # 初始化10级章节的当前编号,初始全为0 current_levels = [0] * 10 for idx, row in df.iterrows(): # 从p_type提取当前层级:HeadingN对应层级N current_level = int(row['p_type'].split('Heading')[1]) if row['sec_id'] != '': # 解析现有章节ID为整数列表 id_parts = list(map(int, row['sec_id'].split('.'))) # 更新对应层级的编号 for i in range(len(id_parts)): current_levels[i] = id_parts[i] # 重置当前层级之后的编号为0,避免干扰后续子章节 for i in range(len(id_parts), 10): current_levels[i] = 0 else: # 空值场景:当前层级编号递增 current_levels[current_level - 1] += 1 # 重置后续层级编号为0 for i in range(current_level, 10): current_levels[i] = 0 # 生成当前章节ID:取前current_level位用.连接 filled_id = '.'.join(map(str, current_levels[:current_level])) df.at[idx, 'sec_id'] = filled_id # 输出验证 print(df['sec_id'].tolist())
代码说明
- 层级跟踪:用
current_levels列表维护每一级章节的最新编号,支持最多10级。 - 层级提取:通过拆分
p_type字符串获取当前章节的层级(如Heading4对应第4级)。 - 非空值处理:解析现有章节ID,更新
current_levels对应位置,并重置后续层级编号,确保后续子章节从0开始递增。 - 空值处理:对当前层级的编号进行递增,重置后续层级编号,生成符合当前层级格式的章节ID。
内容的提问来源于stack exchange,提问作者Dcook
相关产品推荐
相关产品推荐

