skills/skills.netease.im/dimension-definer-pro

dimension-definer-pro

SKILL.md

维度定义处理 Skill Pro v2.1.7

通用型维度定义处理工具,采用5步标准化处理流程,支持从多种输入格式自动提取、匹配、生成标准化的维度定义表。

v2.1.6 重要改进(2026-04-01)

1. 数据逻辑定义输出规则修复

修复问题

  1. 数据逻辑定义使用 definition 中的变量前缀查找值标签,导致找不到值标签时输出 D4a=code1 格式
  2. 多 code 值(如 D3a=3/4)只处理第一个 code,未输出完整的值标签列表

修复方案

  1. 使用匹配到的 var_name 查找值标签:不是使用 definition 中的变量前缀(如 D4a),而是使用匹配到的实际变量名(如 D4_L2_城市级别)
  2. 建立简写变量名映射:值标签表中的变量名是完整形式(如 D2_您的性别是),建立简写到完整的映射关系
  3. 支持多 code 值连接/ 分隔的 code 用 "或" 连接,&, 分隔的 code 用 "且" 连接

修复效果

场景 修复前 修复后
单code,有值标签 D2=code1 D2=男性
多code,有值标签 D3a=code3 D3a=25-29岁或D3a=30-34岁
无值标签 D4a=code1 D4_L2_城市级别=code1

输出规则

  • 使用匹配到的 var_name(不是 definition 中的变量前缀)查找值标签
  • 如果能找到值标签,输出:var_name=值标签
  • 如果找不到值标签,输出:var_name=codeX
  • 多 code 值用 "或" 或 "且" 连接

2. 需求信息列 dim_type 前向填充修复(2026-04-01)

修复问题:3行结构中,需求信息列的 dim_type 只在特定列有值,后续列的 dim_type 为空,导致所有维度值都使用第一个 dim_type(如"城市级别")

根因分析

  1. Banner1 的 3行结构:行3 (Total行) 有 Col2:城市级别, Col7:性别, Col9:年龄
  2. 原代码只在循环外部提取一次 current_dim_type,没有根据列位置动态获取
  3. 结果:Col7 和 Col9 的维度值(男性、女性、<25等)都使用了错误的 dim_type "城市级别"

修复方案

  1. 先读取所有列的 dim_type:遍历 dim_type_row 的所有列,存储到 dim_type_map
  2. 前向填充:如果当前列没有 dim_type,继承左边最近的 dim_type
  3. 循环内部动态获取:根据当前列位置从 dim_type_map 获取 dim_type

修复效果

修复前 修复后
行7 Banner1-人口学-城市级别-男性 Banner1-人口学-性别-男性
行9 Banner1-人口学-城市级别-<25 Banner1-人口学-年龄-<25
行13 Banner1-人口学-城市级别-5万元以下 Banner1-人口学-家庭年收入水平1-5万元以下

输出规则

  • 需求信息格式:Banner名称-维度类型-维度值
  • 3行结构:dim_type 从 Total 行提取,支持前向填充
  • 2行结构:dim_type 为空,使用 banner 名称

3. 智能匹配策略(v2.1.7 新增,2026-04-01)

目标:提升变量名称匹配率,通过需求信息和需求定义进行两级匹配

匹配策略

  1. 第一级:通过需求定义缩小范围

    • 从 Definition 提取变量前缀(如 Q20_A
    • 处理多级题号(D8-1D8_1
    • 处理双下划线格式(Q20_AQ20__SQ1
    • 子题号映射(ASQ1, BSQ2
  2. 第二级:通过需求信息关键词筛选

    • 提取平台关键词(携程、去哪儿、飞猪等)
    • 提取业务/分类关键词(酒店、机票、在线智能等)
    • 计算匹配得分,选择最佳候选

匹配效果

版本 自动匹配率 提升
v2.1.6 (修复前) 61.0% -
v2.1.7 (智能匹配) 91.8% +30.8%

匹配类型分布

匹配类型 数量 占比
自动匹配(智能) 87 44.6%
自动匹配(派生) 48 24.6%
自动匹配 41 21.0%
自动匹配(前缀) 3 1.5%
自动匹配总计 179 91.8%
需人工审核 16 8.2%

示例

  • Q20_A=1 + 携程-酒店Q20__SQ1_1 (自动匹配(智能))
  • D8_A=2 + 携程-电话D8_SQ1_2 (自动匹配(智能))
  • D8-1_A=1 + 携程-在线智能D8_1_SQ1_1 (自动匹配(智能))

4. 城市级别特殊匹配与数据逻辑定义修复(v2.1.7 新增,2026-04-01)

修复问题1:城市级别匹配

  • 城市级别维度(如"一线城市")应该匹配到 H1 变量,而不是 D4_L2_城市级别
  • 四五城市等特殊组合需要正确匹配到多个值标签

修复方案

  1. 优先在值标签表中匹配 dim_value:查找包含"一线城市"等标签的变量
  2. 处理组合城市:如"四五城市"匹配到"四线城市"和"五线城市"
  3. 变量名映射:值标签表中的变量名可能是完整形式(如"H1_城市级别映射关系"),需要映射到简写形式(H1)

修复效果

需求 修复前 修复后
Banner1-城市级别-一线城市 D4_L2_城市级别=code1 H1=一线城市
Banner1-城市级别-四五城市 D4_L2_城市级别=code5或code6 H1=四线城市或H1=五线城市

修复问题2:数据逻辑定义模糊匹配

  • 值标签表中的变量名是完整形式(如"Q4 _SQ1_请根据您的体验...")
  • 代码中使用的是简写形式(如"Q4__SQ1")
  • 导致无法正确查找值标签,输出 codeX 而不是中文标签

修复方案

  1. 模糊匹配:在 _get_value_label 方法中,查找包含简写变量名的完整变量名
  2. 格式转换:处理双下划线格式(Q4__SQ1Q4 _SQ1

修复效果

变量 修复前 修复后
Q4__SQ1 Q4__SQ1=code4 Q4__SQ1=比较满意

修复问题3:多选题默认值标签

  • 多选题变量(如 D6_A1, D6_A2)在值标签表中只有变量名行,没有 code 行
  • 这些变量应该使用默认值标签 {0: '否', 1: '是'}

修复方案

  1. 自动识别多选题变量:包含 _A1, _A2 等子题号的变量
  2. 添加默认值标签:为没有值标签的多选题变量添加 {0: '否', 1: '是'}

修复效果

  • 值标签表从 1092 条增加到 2290 条
  • D6_1, D6_2 等变量现在有完整的值标签

5. 值标签解析逻辑修复(v2.1.7 新增,2026-04-01)

修复问题:多选题变量(如 D5_A1, D6_A1)的值标签被错误地归到前一个变量

根因分析

  1. 多选题变量在值标签表中的格式:
    • 变量名行:│D5_A1_最近一年...:国内旅行/出行│否│(没有 code)
    • code 行:│(空)│1.00│是│(first_part 为空)
  2. 原代码只在有 code 的行更新 current_var,导致 code 行的值标签被归到前一个变量

修复方案

  1. 处理变量名行:在没有 code 但有标签的行,更新 current_var 但不添加值标签
  2. 正确处理多选题格式:识别 │变量名│标签│ 格式的行

修复效果

  • D10 的值标签正确解析:code 1-6 对应正确的标签
  • 多选题变量(D5_A1, D6_A1 等)的值标签正确归到各自变量

6. 多选题数据逻辑定义修复(v2.1.7 新增,2026-04-01)

修复问题1:D10 数据逻辑定义输出错误

  • 错误输出D10=是或D10=听说过,但没有使用过
  • 正确输出D10=我不知道什么是AI工具或D10=听说过,但没有使用过

根因分析

  1. D10 的值标签被多选题默认值 {0: '否', 1: '是'} 覆盖
  2. 多选题默认值标签被错误地添加到了 D10

修复方案

  1. 修复值标签解析逻辑,确保 D10 的值标签正确解析
  2. 多选题默认值只添加到真正的多选题变量(有子题号如 _A1, _A2)

修复效果

变量 修复前 修复后
D10 D10=是或D10=听说过... D10=我不知道什么是AI工具或D10=听说过...

修复问题2:多选题数据逻辑定义规则不完善

  • 场景1:dim_value 表示"是"的情况(如"去哪儿")→ 输出 =是
  • 场景2:dim_value 表示"否"的情况(如"以上都没有")→ 输出 =否
  • 场景3:definition 包含"≠"(如"D8_A≠99")→ 输出 =否

修复方案

  1. 关键词判断:dim_value 包含"没有"、"未"、"无"、"以上都没有"等表示"否"
  2. 符号判断:definition 包含"≠"表示"否"
  3. 综合判断:结合关键词和符号判断"是"或"否"

修复效果

场景 示例 修复后
dim_value="去哪儿" D6=2 D6_2=是
dim_value="以上都没有" D8_A≠99 D8_SQ1_99=否
definition 含"≠" D8_A≠99 D8_SQ1_99=否

v2.1.5 重要改进

1. 值标签解析完整性修复(2026-03-31)

修复问题:值标签解析失败,解析结果为0条

根因分析

  1. 实际文件格式:│变量名(大量空格)code│标签│,code位于行尾
  2. 原正则 (\d+\.\d+|\.\d+)\s+(.+)$ 期望code后有内容,但实际code在行尾
  3. 原逻辑无法正确处理这种格式

修复方案

  1. 改进正则:使用 (\d+\.\d+)\s*$ 从行尾匹配code
  2. 改进变量名提取first_part[:match.start()].strip() 提取code前的变量名
  3. 正确处理空变量名行:继承上一个变量名

修复效果

  • 值标签解析:0条 → 1092条
  • 涉及变量:0个 → 96个

2. Banner表结构检测修复(2026-03-31)

修复问题:2行/3行结构检测错误,导致维度信息混乱

根因分析

  1. 原检测逻辑:检查 row_plus_1 是否包含 =
  2. 问题:Banner2的2行结构中,row_plus_1 就是definition(含=),被误判为3行结构
  3. 结果:dim_value和definition错位,dim_type提取错误

修复方案

  1. 多维度检测
    • 检查 row_plus_1 是 dim_value(纯中文)还是 definition(含=
    • 如果是 dim_value,再检查 row_plus_2 是否有 definition
  2. 正确区分结构
    • 3行结构:dim_type_row = total_row, dim_value_row = total_row+1, def_row = total_row+2
    • 2行结构:dim_type_row = None, dim_value_row = total_row, def_row = total_row+1
  3. 正确提取dim_type:3行结构从第2列开始查找(跳过Total列)

修复效果

  • 维度信息格式:从 Banner1-人口学--城市级别 修复为 Banner1-人口学-城市级别-一线城市
  • 条件列:正确填充
  • 需求定义:正确定义
  • 自动匹配率:从 17.9% 提升到 61.0%

3. 多级题号匹配(D8-1, D8-2等)(原有)

场景:Banner7-联系过智能/电话自助/人工

Definition dim_value 匹配变量
D8-1_A=1 在线智能-携程 D8-1_SQ1_A1_您使用的在线客服是以下哪种形式?-携程:在线智能/机器客服
D8-2_A=1 电话自助-携程 D8-2_SQ1_A1_您使用的电话客服是以下哪种形式?-携程:电话语音自助客服

匹配逻辑

# 提取基础题号和子题号
base_code = "D8-1"  # 基础题号
sub_code = "A"      # 子题号

# 查找候选变量
for var_name in variables:
    if var_name.startswith(base_code + "_"):
        # 检查平台匹配(携程→SQ1)
        # 检查分类匹配(在线智能/电话自助)
        # 检查子题号匹配(A→A1)

4. 值标签反向匹配(原有)

场景:D10=1/2 且 dim_value="没有用过AI"

匹配逻辑

# 1. 查找候选变量(以D10开头)
candidates = [var for var in variables if var.startswith("D10_")]

# 2. 检查code 1/2对应的值标签
for var in candidates:
    label_1 = value_labels[var]["1"]  # "我不知道什么是AI工具"
    label_2 = value_labels[var]["2"]  # "听说过,但没有使用过"
    
    # 3. 检查值标签是否与dim_value匹配
    if "没有" in label_1 and "没有" in dim_value:
        # 匹配成功

关键词映射

dim_value关键词 值标签匹配词
没有用过 不知道、没有使用、没用过
使用过 使用过、用过、正在使用
低频 偶尔、有时、很少
高频 经常、频繁、总是

5. 复合维度值匹配优化(原有)

场景:Q7_A=1 且 dim_value="携程-使用过"

匹配逻辑

# 1. 提取平台和状态
platform = "携程"  # 从dim_value提取
status = "使用过"  # 从dim_value提取

# 2. 查找候选变量
for var_name in variables:
    if var_name.startswith("Q7_") and "携程" in var_label:
        # 3. 检查code 1对应的值标签是否为"使用过"
        if value_labels[var_name]["1"] == "使用过":
            # 匹配成功: Q7_SQ1_最近一年...

变量匹配准确率提升

新增匹配策略

1. 多级题号匹配(D8-1, D8-2等)

场景:Banner7-联系过智能/电话自助/人工

Definition dim_value 匹配变量
D8-1_A=1 在线智能-携程 D8-1_SQ1_A1_您使用的在线客服是以下哪种形式?-携程:在线智能/机器客服
D8-2_A=1 电话自助-携程 D8-2_SQ1_A1_您使用的电话客服是以下哪种形式?-携程:电话语音自助客服

匹配逻辑

# 提取基础题号和子题号
base_code = "D8-1"  # 基础题号
sub_code = "A"      # 子题号

# 查找候选变量
for var_name in variables:
    if var_name.startswith(base_code + "_"):
        # 检查平台匹配(携程→SQ1)
        # 检查分类匹配(在线智能/电话自助)
        # 检查子题号匹配(A→A1)

2. 值标签反向匹配

场景:D10=1/2 且 dim_value="没有用过AI"

匹配逻辑

# 1. 查找候选变量(以D10开头)
candidates = [var for var in variables if var.startswith("D10_")]

# 2. 检查code 1/2对应的值标签
for var in candidates:
    label_1 = value_labels[var]["1"]  # "我不知道什么是AI工具"
    label_2 = value_labels[var]["2"]  # "听说过,但没有使用过"
    
    # 3. 检查值标签是否与dim_value匹配
    if "没有" in label_1 and "没有" in dim_value:
        # 匹配成功

关键词映射

dim_value关键词 值标签匹配词
没有用过 不知道、没有使用、没用过
使用过 使用过、用过、正在使用
低频 偶尔、有时、很少
高频 经常、频繁、总是

3. 复合维度值匹配优化

场景:Q7_A=1 且 dim_value="携程-使用过"

匹配逻辑

# 1. 提取平台和状态
platform = "携程"  # 从dim_value提取
status = "使用过"  # 从dim_value提取

# 2. 查找候选变量
for var_name in variables:
    if var_name.startswith("Q7_") and "携程" in var_label:
        # 3. 检查code 1对应的值标签是否为"使用过"
        if value_labels[var_name]["1"] == "使用过":
            # 匹配成功: Q7_SQ1_最近一年...

改进效果

  • 匹配率:从 71% → 目标 85%+
  • 匹配准确率:显著提升(减少误匹配)
  • 复杂条件处理:支持多级题号、值标签反向验证

v2.1.4 重要改进

需求定义输出格式优化

改进背景:用户反馈需求定义列应直接输出原始Definition,而非拼接中文描述

改进前

  • 输出:城市级别-一线城市是D4a=1
  • 问题:包含中文描述前缀,不符合用户需求

改进后

  • 输出:D4a=1
  • 优势:直接使用原始Definition,简洁清晰

复杂条件支持

原始Definition 改进前输出 改进后输出
D9_A仅选中1 售前&售后-携程是D9_A仅选中1 D9_A仅选中1
D10=1/2 没有用过AI-D10=1/2 D10=1/2
D9_A选中1,且选中2/3/4 售前&售后-携程是D9_A选中1,且选中2/3/4 D9_A选中1,且选中2/3/4

Banner表结构自适应检测

问题:不同Banner采用不同的表结构(2行 vs 3行)

解决方案

# 检测方法:检查Row+1的Col3是否包含=或≠
if row_plus_1_has_def:
    dim_type_row = total_row      # 3行结构
    dim_value_row = total_row + 1
    definition_row = total_row + 2
else:
    dim_type_row = None           # 2行结构
    dim_value_row = total_row
    definition_row = total_row + 1

改进效果

  • 匹配率:从 50% → 71% (+21%)
  • 需求定义准确性:大幅提升
  • 复杂条件处理:正确保留原始格式

v2.1.3 重要修复

值标签解析完整性修复

修复问题:值标签表解析不完整,遗漏大量变量

根因分析

  1. 正则表达式 (\d+\.?\d*) 无法匹配 .00 格式(前面没有数字)
  2. 依赖分隔线(├─)判断变量分组,但文件中很多变量连续排列无分隔线
  3. 变量名继承逻辑在遇到分隔线时重置,导致后续变量丢失

修复方案

  1. 改进正则:使用 ((?:\d+)?\.\d+) 支持可选数字前缀的小数(如 .00, 1.00
  2. 改进分组逻辑:通过变量名存在性判断新变量开始,不依赖分隔线
  3. 保留原始code:对于 .00 格式,可选择保留或标准化为 0

修复效果

  • 变量数量:从 96个 → 692个(+620%)
  • 值标签条目:从 1092条 → 完整提取
  • 遗漏变量示例:D1_A1-D1_A8(8个变量,之前全部遗漏)

代码变更

  • 更新函数:parse_value_sheet_fixed()parse_value_sheet_fixed_v213()
  • 关键改进:
    # 旧正则(不支持 .00)
    match = re.search(r'(\d+\.?\d*)\s+([^\d].+)$', content)
    
    # 新正则(支持 .00)
    match = re.search(r'((?:\d+)?\.\d+)\s+([^\d].+)$', content)
    
    # 旧分组逻辑(依赖分隔线)
    if line.startswith('├'):  # 分隔线表示变量结束
    
    # 新分组逻辑(通过变量名存在性)
    if var_name and var_name != '':  # 变量名存在表示新变量
    

v2.1.2 新增功能

数据逻辑定义智能转换

新增功能:数据逻辑定义自动转换为中文标签

转换规则

输入 值标签 输出
D2=1 {1: '男性', 2: '女性'} D2=男性
D3a=3/4 {3: '25-29岁', 4: '30-34岁'} D3a=25-29岁或D3a=30-34岁
D7_E=3 {0: '否', 1: '是'} D7_5_3=是

转换逻辑

  1. 从值标签表查找code对应的中文标签
  2. / 转换为"或"(多选)
  3. , 转换为"且"(同时满足)
  4. 多选题自动识别,输出"=是"

v2.1.1 新增功能

通用多级嵌套匹配

新增匹配能力:基于多维度信息交叉验证的通用匹配方法

匹配要素

  1. 题号前缀:从Definition提取(如 D8)
  2. 一级分类:从维度类型提取(如 在线客服)
  3. 平台+二级分类:从维度值提取(如 携程-在线)
  4. Code:从Definition提取(如 1)

匹配示例

Definition 维度类型 维度值 匹配变量
D8_A=1 在线客服 携程-在线 D8_SQ1_1
D8_B=1 在线客服 去哪儿-在线 D8_SQ2_1
D8_A=2 电话客服 携程-电话 D8_SQ1_2
D8-1_A=1 在线智能 携程-在线智能 D8_1_SQ1_1

匹配逻辑

变量名以题号前缀开头 (D8*)
AND 变量标签包含平台名 (携程)
AND 变量标签包含分类关键词 (在线客服)
AND 变量名结尾匹配code (_1)
→ 最佳匹配: D8_SQ1_1

适用场景:Banner7-联系过智能/电话自助/人工 等复杂嵌套结构

v2.1.0 重要修复

修复问题

问题 根因 修复方案
Banner解析不完整 错误理解Total行结构,维度类型行定位错误 Total行同时是维度类型行,添加前向填充逻辑
需求信息格式错误 混淆维度类型和维度值 正确解析三行结构(类型/值/Definition)
变量标签截断 代码中有 [:100] 截断 移除截断,输出完整标签
值标签不完整 code行变量名为空时未继承 使用 current_var 跟踪确保code正确关联
匹配率低 只支持简单变量匹配 新增子变量、复合维度值、三级题号匹配

修复效果

  • Banner解析:从部分输出 → 完整13个Banner
  • 匹配率:从 27.54% → 78.26% (+50.72%)
  • 标签输出:从100字符截断 → 完整输出

5步处理流程概览

┌─────────────────────────────────────────────────────────────────┐
│                    5步标准化处理流程                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  【Step 1: 格式识别与解析】                                        │
│     ├─ 自动检测输入文件格式(SPSS编码表/Banner表/问卷定义表)        │
│     ├─ 解析三个核心Sheet:Banner表、变量表、值标签表                │
│     └─ 提取维度需求、变量定义、值标签映射                           │
│                          ↓                                      │
│  【Step 2: 数据清洗与标准化】                                      │
│     ├─ 去除无效数据(分隔线、空行、表头)                          │
│     ├─ 标准化变量名(统一大小写、去除空格)                         │
│     ├─ 数值解析(从右向左查找code值)                              │
│     └─ 处理混合结构(类型A/B识别)                                │
│                          ↓                                      │
│  【Step 3: 数据整理】                                             │
│     ├─ 条件拆分(&符号→且,|符号→或)                              │
│     ├─ 生成需求定义(条件组合)                                    │
│     └─ 结构化存储(便于后续匹配)                                  │
│                          ↓                                      │
│  【Step 4: 维度匹配与定义生成】                                    │
│     ├─ 三级匹配策略:                                             │
│     │   ① 从Definition精确提取变量名(如D4a=1→D4A)               │
│     │   ② 精确匹配维度类型到变量表                                │
│     │   ③ 模糊匹配(相似度算法)                                  │
│     ├─ 生成数据逻辑定义(展开范围、连接符号)                       │
│     ├─ 生成新变量名(banner{序号}_{维度序号}_{值序号})            │
│     └─ 生成code(每个维度内从1递增)                              │
│                          ↓                                      │
│  【Step 5: 质量检查与报告】                                        │
│     ├─ 5.1 完整性检查(未匹配项、缺失值标签、不完整逻辑)           │
│     ├─ 5.2 来源验证(验证匹配结果是否来自源表)                    │
│     ├─ 5.3 匹配率计算(自动/模糊/需审核分类统计)                   │
│     ├─ 5.4 输出文件(待审核版 + 最终版)                          │
│     └─ 5.5 处理报告(Markdown格式详细报告)                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

详细处理步骤

Step 1: 格式识别与解析

1.1 检测文件格式

格式类型 检测特征 处理方法
SPSS编码表 包含"变量"和"值标签"sheet 解析变量表和值标签表
Banner横向交叉表 多列结构,Banner在行 横向解析,提取维度层级
Banner纵向列表 少列结构,Banner在列 纵向解析,提取定义

1.2 解析三个核心Sheet

def step1_parse_files(file_path):
    """Step 1: 解析三个Sheet"""
    wb = openpyxl.load_workbook(file_path)
    
    # 1.1 解析Banner表
    ws_banner = wb['Banner']
    banner_data = parse_banner_sheet(ws_banner)
    
    # 1.2 解析变量表(SPSS格式)
    ws_var = wb['变量']
    var_data = parse_var_sheet(ws_var)
    
    # 1.3 解析值标签表(SPSS格式)
    ws_value = wb['值标签']
    value_data = parse_value_sheet(ws_value)
    
    return banner_data, var_data, value_data

1.3 Banner表解析(处理混合结构)

Banner表存在两种结构类型:

  • 类型A: dim_type是维度类型(如"城市级别"),dim_value_def是Definition(如"D4a=1")
  • 类型B: dim_type本身就是Definition(如"D10=1/2")
def parse_banner_sheet_v3(ws):
    """
    解析Banner表(v2.1.0修复版)
    
    关键修复:
    1. Total行(行26)同时也是维度类型行,不是下一行
    2. 维度类型行需要前向填充(继承左边最近的维度类型)
    3. 正确区分维度类型、维度值、Definition三行
    
    结构:
    - 行25: Banner标题
    - 行26: Total + 维度类型(稀疏填充,列3="是否联系过平台客服",列8="经服业务线-携程")
    - 行27: 维度值(列3="携程",列8="酒店-携程")
    - 行28: Definition(列3="D8_A≠99",列8="D7_A=1")
    """
    items = []
    row_idx = 1
    
    while row_idx <= ws.max_row:
        first_cell = ws.cell(row_idx, 1).value
        
        if first_cell and str(first_cell).startswith('Banner'):
            current_banner = str(first_cell).strip()
            
            # 查找Total行
            total_row = None
            for check_row in range(row_idx + 1, min(row_idx + 5, ws.max_row + 1)):
                cell2 = ws.cell(check_row, 2).value
                if cell2 and str(cell2).strip() == 'Total':
                    total_row = check_row
                    break
            
            if not total_row:
                row_idx += 1
                continue
            
            # 关键修复:Total行就是维度类型行
            dim_type_row = total_row
            value_row = total_row + 1
            def_row = total_row + 2
            
            # 读取三行数据
            dim_types = {}
            dim_values = {}
            definitions = {}
            
            for col in range(2, ws.max_column + 1):
                dim_types[col] = ws.cell(dim_type_row, col).value
                dim_values[col] = ws.cell(value_row, col).value
                definitions[col] = ws.cell(def_row, col).value
            
            # 关键修复:前向填充维度类型
            last_type = None
            for col in sorted(dim_types.keys()):
                if dim_types[col]:
                    last_type = str(dim_types[col]).strip()
                elif last_type and dim_values[col]:
                    # 继承左边最近的维度类型
                    dim_types[col] = last_type
            
            # 生成条目
            for col in dim_values.keys():
                if dim_values[col]:
                    dim_type = str(dim_types[col]).strip() if dim_types[col] else ""
                    dim_value = str(dim_values[col]).strip()
                    definition = str(definitions[col]).strip() if definitions[col] else ""
                    
                    # 判断结构类型
                    if '=' in dim_type:
                        # 类型B: dim_type就是Definition
                        items.append({
                            'banner': current_banner,
                            'dim_type': dim_value,
                            'dim_value': dim_value,
                            'definition': dim_type,
                            'row': row_idx,
                            'col': col
                        })
                    else:
                        # 类型A: 正常结构
                        items.append({
                            'banner': current_banner,
                            'dim_type': dim_type,
                            'dim_value': dim_value,
                            'definition': definition,
                            'row': row_idx,
                            'col': col
                        })
            
            row_idx = def_row + 1
        else:
            row_idx += 1
    
    return items

1.4 变量表解析(SPSS格式)

def parse_var_sheet(ws):
    """解析变量表(SPSS导出格式)"""
    variables = {}
    
    for row in ws.iter_rows(min_row=5, values_only=True):
        if not row or len(row) < 1:
            continue
        
        row_text = str(row[0]) if row[0] else ""
        
        # 跳过分隔线
        if any(c in row_text for c in ['─', '├', '╭', '╰']):
            continue
        
        # 解析SPSS格式:│名称│位置│标签│...
        match = re.search(r'│\s*(\w+)\s*│\s*\d+\s*│\s*([^│]+)│', row_text)
        if match:
            var_name = match.group(1).strip()
            var_label = match.group(2).strip()
            if var_name and var_name != '名称':
                variables[var_name] = {
                    'name': var_name,
                    'label': var_label
                }
    
    return variables

1.5 值标签表解析(SPSS格式 - v2.1.3修复版)

⚠️ 重要修复:处理单行混合格式,确保所有code都被正确解析

v2.1.3 修复内容

  1. 支持 .00 格式:处理值标签为 .00(前面没有数字)的情况,如 .00 否
  2. 改进变量分组逻辑:不依赖分隔线,通过变量名存在性判断新变量开始
  3. 更健壮的code提取:支持 (\d+)?\.\d+ 格式(可选数字前缀的小数)
def parse_value_sheet_fixed(ws):
    """
    解析值标签表(SPSS导出格式 - v2.1.3修复版)
    
    修复问题:
    1. 处理单行混合格式(变量名和code在同一行)
    2. 继承变量名(code行变量名为空时使用上一个变量名)
    3. 确保所有code都被正确关联到对应变量
    4. 【v2.1.3新增】支持 .00 格式(如 .00 否)
    5. 【v2.1.3新增】不依赖分隔线,正确处理连续变量
    
    输入格式示例:
    │D2_您的性别是                                                                                           1.00  男性│
    │                                                                                                       2.00  女性│
    │D1_A1_请问您最近3个月是否接受过以下品类的市场调查?:旅行/出行类                                         .00   否│
    │                                                                                                       1.00  是│
    """
    value_labels = {}
    current_var = None
    
    for i in range(5, ws.max_row + 1):
        cell_value = ws.cell(i, 1).value
        if not cell_value:
            continue
        
        row_text = str(cell_value)
        
        # 跳过分隔线
        if any(c in row_text for c in ['─', '├', '╭', '╰']) or 'Variable' in row_text:
            continue
        
        # 去除│和前后空格
        content = row_text.replace('│', '').rstrip()
        if not content:
            continue
        
        # 【v2.1.3修复】从右向左查找code模式
        # 支持格式:1.00, 2.00, .00(前面没有数字)
        # 正则:(\d+)?\.\d+ 表示可选的数字前缀 + 小数点 + 数字
        match = re.search(r'((?:\d+)?\.\d+)\s+([^\d].+)$', content)
        if match:
            code = match.group(1).strip()
            label = match.group(2).strip()
            
            # 提取变量名(code之前的所有内容)
            var_end = content.rfind(match.group(0))
            var_name = content[:var_end].strip()
            
            # 【v2.1.3修复】标准化code
            # 对于 .00 格式,保留原始格式或转换为 0
            if code.startswith('.'):
                code_normalized = '0'  # 或者保留 code = code
            else:
                code_normalized = str(int(float(code)))
            
            # 【v2.1.3修复】关键逻辑:通过变量名存在性判断新变量
            # 如果变量名不为空,说明是新变量的开始
            if var_name and var_name != '':
                # 保存之前的变量(如果有)
                if current_var and current_var in value_labels and value_labels[current_var]:
                    pass  # 已保存
                current_var = var_name
                if current_var not in value_labels:
                    value_labels[current_var] = {}
            
            # 使用current_var确保code被正确关联
            if current_var:
                if current_var not in value_labels:
                    value_labels[current_var] = {}
                value_labels[current_var][code_normalized] = label
    
    return value_labels

v2.1.3 关键改进说明

问题 v2.1.2及之前 v2.1.3修复
.00 格式 无法识别 .00 否 支持 (\d+)?\.\d+ 正则,正确识别
变量分组 依赖分隔线(├─)分组 通过变量名存在性判断,不依赖分隔线
连续变量 分隔线后误认为是新变量 正确处理连续排列的变量
变量数量 96个(遗漏大量变量) 692个(完整提取)

修复效果示例

D1_A1变量(之前遗漏)

│D1_A1_请问您最近3个月是否接受过以下品类的市场调查?:旅行/出行类                                         .00   否│
│                                                                                                       1.00  是│
  • v2.1.2: ❌ 未识别(.00格式不支持)
  • v2.1.3: ✅ 正确识别,提取2个值标签(.00→否, 1.00→是)

数据通道变量(之前被截断)

│数据通道                                                                                                                                                                                                         2.00  │私域通道│
│                                                                                                                                                                                                         3.00  │第三方通道│
...(连续48个值标签,无分隔线)
  • v2.1.2: ❌ 只提取4个(遇到分隔线后停止)

  • v2.1.3: ✅ 完整提取48个值标签

    return value_labels


### Step 2: 数据清洗与标准化

**2.1 清洗规则**

```python
def step2_clean_data(banner_data, var_data, value_data):
    """Step 2: 数据清洗与标准化"""
    
    # 清洗Banner数据
    cleaned_banner = []
    for item in banner_data:
        if not item['dim_type']:
            continue
        
        # 标准化
        item['dim_type'] = item['dim_type'].strip()
        item['dim_value'] = item['dim_value'].strip().replace('\n', ' ') if item['dim_value'] else item['dim_type']
        item['definition'] = item['definition'].strip() if item['definition'] else None
        
        cleaned_banner.append(item)
    
    # 标准化变量名(大写)
    cleaned_var = {}
    for var_name, var_info in var_data.items():
        clean_name = var_name.upper().strip()
        cleaned_var[clean_name] = var_info
    
    # 标准化值标签
    cleaned_value = {}
    for var_name, codes in value_data.items():
        clean_name = var_name.upper().strip()
        cleaned_value[clean_name] = {}
        for code, label in codes.items():
            clean_code = str(code).strip()
            cleaned_value[clean_name][clean_code] = label.strip()
    
    return cleaned_banner, cleaned_var, cleaned_value

Step 3: 数据整理

3.0 Banner表解析(v2.1.4重要改进)

⚠️ 重要改进:自适应检测Banner表结构(2行 vs 3行)

问题背景:不同Banner采用不同的表结构

  • 3行结构(如Banner1): Total行=dim_type, 下一行=dim_value, 再下一行=definition
  • 2行结构(如Banner2): Total行=dim_value, 下一行=definition

检测方法:检查Total行的下一行(Row+1)的Col3是否包含=

  • 如果包含 → 3行结构(Row+1是dim_value,包含definition格式)
  • 如果不包含 → 2行结构(Row+1是definition)
def parse_banner_sheet_adaptive(ws):
    """
    自适应解析Banner表(v2.1.4改进版)
    
    支持两种结构:
    1. 3行结构: dim_type行 → dim_value行 → definition行
    2. 2行结构: dim_value行(Total行) → definition行
    """
    items = []
    row_idx = 1
    
    while row_idx <= ws.max_row:
        first_cell = ws.cell(row_idx, 1).value
        
        if first_cell and str(first_cell).startswith('Banner'):
            current_banner = str(first_cell).strip()
            
            # 查找Total行
            total_row = None
            for check_row in range(row_idx + 1, min(row_idx + 5, ws.max_row + 1)):
                cell2 = ws.cell(check_row, 2).value
                if cell2 and str(cell2).strip() == 'Total':
                    total_row = check_row
                    break
            
            if not total_row:
                row_idx += 1
                continue
            
            # 【v2.1.4关键改进】自适应检测结构
            # 检查Row+1的Col3是否包含=或≠
            row_plus_1 = total_row + 1
            row_plus_1_has_def = False
            for col in range(3, 20):
                val = ws.cell(row_plus_1, col).value
                if val and ('=' in str(val) or '≠' in str(val)):
                    row_plus_1_has_def = True
                    break
            
            if row_plus_1_has_def:
                # 3行结构
                dim_type_row = total_row
                dim_value_row = total_row + 1
                definition_row = total_row + 2
            else:
                # 2行结构
                dim_type_row = None
                dim_value_row = total_row
                definition_row = total_row + 1
            
            # 读取数据...
            # (后续逻辑与之前版本相同)
            
            row_idx = definition_row + 1
        else:
            row_idx += 1
    
    return items

3.1 条件拆分

def step3_organize_data(banner_data):
    """Step 3: 数据整理"""
    requirements = []
    
    for item in banner_data:
        req = {
            'banner': item['banner'],
            'dim_type': item['dim_type'],
            'dim_value': item['dim_value'],
            'original_def': item.get('definition'),
            'conditions': []
        }
        
        # 3.2 条件拆分
        dim_type = item['dim_type']
        
        # 处理 & 符号(且)
        if '&' in dim_type:
            parts = dim_type.split('&')
            for i, part in enumerate(parts, 1):
                req['conditions'].append({
                    'condition_col': f'条件{i}',
                    'type': 'and',
                    'value': part.strip()
                })
        # 处理 | 符号(或)
        elif '|' in dim_type and '=' not in dim_type:
            parts = dim_type.split('|')
            for i, part in enumerate(parts, 1):
                req['conditions'].append({
                    'condition_col': f'条件{i}',
                    'type': 'or',
                    'value': part.strip()
                })
        # 单条件
        else:
            req['conditions'].append({
                'condition_col': '条件1',
                'type': 'single',
                'value': dim_type
            })
        
        # 3.3 生成需求定义(v2.1.4改进)
        # 直接使用definition列的内容,不进行额外处理
        if req['original_def']:
            req['demand_def'] = req['original_def']
        else:
            req['demand_def'] = ""
        
        requirements.append(req)
    
    return requirements

v2.1.4 改进说明

项目 v2.1.3及之前 v2.1.4改进
Banner结构 固定3行结构 自适应2行/3行结构
需求定义 拼接中文描述(如"城市级别-一线城市是D4a=1") 直接使用definition(如"D4a=1")
复杂条件 无法正确处理 保留原始格式(如"D9_A仅选中1")
匹配率 50-60% 70%+

Step 4: 维度匹配与定义生成

4.0 数据逻辑定义生成函数(v2.1.6 修复版)

def _get_value_label(self, var_name: str, code: str) -> Optional[str]:
    """
    获取指定变量和code对应的值标签
    
    支持简写变量名映射(如 D2 -> D2_您的性别是)
    """
    if var_name in self.var_value_dict and code in self.var_value_dict[var_name]:
        return self.var_value_dict[var_name][code]
    elif '_' in var_name:
        # 尝试简写名称(第一个下划线之前的部分)
        short_name = var_name.split('_')[0]
        if short_name in self.var_name_mapping:
            full_name = self.var_name_mapping[short_name]
            if full_name in self.var_value_dict and code in self.var_value_dict[full_name]:
                return self.var_value_dict[full_name][code]
    elif var_name in self.var_name_mapping:
        # var_name 本身就是简写名称
        full_name = self.var_name_mapping[var_name]
        if full_name in self.var_value_dict and code in self.var_value_dict[full_name]:
            return self.var_value_dict[full_name][code]
    return None

def _generate_data_logic(self, var_name: str, definition: str) -> str:
    """
    生成数据逻辑定义(v2.1.6 修复版)
    
    规则:
    1. 使用匹配到的 var_name(不是 definition 中的变量前缀)查找值标签
    2. 支持多个code值,用"或"或"且"连接
    3. 如果能找到值标签,输出:var_name=值标签
    4. 如果找不到值标签,输出:var_name=codeX
    
    连接符规则:
    - / 表示"或"
    - & 或 , 表示"且"
    
    示例:
    - var_name='D2', definition='D2=1' -> 'D2=男性'
    - var_name='D3a', definition='D3a=3/4' -> 'D3a=25-29岁或D3a=30-34岁'
    - var_name='F5', definition='F5=5/6/7' -> 'F5=51-100万元或F5=101-200万元或F5=200万元以上'
    - var_name='D4_L2_城市级别', definition='D4a=1' -> 'D4_L2_城市级别=code1'
    """
    if not var_name or not definition:
        return ''
    
    # 从 definition 中提取 codes 和连接符
    codes = []
    connector = ''  # '或' 或 '且'
    
    if '≠' in definition:
        parts = definition.split('≠')
        if len(parts) == 2:
            code = parts[1].strip()
            codes = [code]
    elif '=' in definition:
        match = re.match(r'(\w+)=(.+)', str(definition))
        if match:
            codes_part = match.group(2)
            # 判断连接符:/ 表示"或",& 或 , 表示"且"
            if '/' in codes_part:
                codes = [c.strip() for c in codes_part.split('/')]
                connector = '或'
            elif '&' in codes_part:
                codes = [c.strip() for c in codes_part.split('&')]
                connector = '且'
            elif '|' in codes_part:
                codes = [c.strip() for c in codes_part.split('|')]
                connector = '或'
            else:
                codes = [codes_part.strip()]
    
    if not codes:
        return definition
    
    # 为每个 code 查找值标签
    value_parts = []
    for code in codes:
        value_label = self._get_value_label(var_name, code)
        if value_label:
            value_parts.append(f"{var_name}={value_label}")
        else:
            value_parts.append(f"{var_name}=code{code}")
    
    # 用连接符连接多个值
    if len(value_parts) > 1 and connector:
        return connector.join(value_parts)
    elif value_parts:
        return value_parts[0]
    else:
        return definition

关键修复说明(v2.1.6)

  1. 使用匹配到的 var_name 查找值标签:不是使用 definition 中的变量前缀(如 D4a),而是使用匹配到的实际变量名(如 D4_L2_城市级别)

  2. 支持简写变量名映射:值标签表中的变量名通常是完整形式(如 D2_您的性别是),而匹配到的变量名可能是简写形式(如 D2)。通过 var_name_mapping 建立映射关系

  3. 支持多 code 值连接

    • / 分隔的 code 用 "或" 连接
    • &, 分隔的 code 用 "且" 连接
  4. 区分两种情况

    • 能找到值标签 → 输出 var_name=值标签
    • 找不到值标签 → 输出 var_name=codeX

4.1 增强匹配策略(修复版)

⚠️ 重要改进:新增复合维度值匹配、三级题号匹配、语义一致性验证

def step4_match_dimensions(requirements, var_data, value_data):
    """
    Step 4: 维度匹配与定义生成(增强版)
    
    匹配策略(按优先级):
    1. 直接匹配:从Definition精确提取变量名
    2. 子变量匹配:题号+code匹配(如D6=1→D6_1)
    3. 复合维度值匹配:处理"酒店-携程"等多部分维度值
    4. 三级题号匹配:处理D7_A=1→D7_1_1等复杂题号
    5. 语义一致性验证:验证业务语义匹配度
    """
    
    for req in requirements:
        original_def = req.get('original_def', '')
        dim_value = req['dim_value']
        dim_type = req['dim_type']
        matched_var = None
        match_type = '需人工审核'
        confidence = '0%'
        
        if original_def and '=' in original_def:
            # 提取题号(支持多级如 D7_A, Q20_A)
            var_candidate = original_def.split('=')[0].strip()
            code_value = original_def.split('=')[1].strip() if '=' in original_def else ''
            
            # 第一级:直接匹配(如 D2, F5 等简单变量)
            if var_candidate.upper() in var_data:
                matched_var = var_candidate.upper()
                match_type = '自动匹配'
                confidence = '95%'
            elif var_candidate in var_data:
                matched_var = var_candidate
                match_type = '自动匹配'
                confidence = '95%'
            else:
                # 第二级:通用多级嵌套匹配(新增 v2.1.1)
                # 基于多维度信息交叉验证的通用匹配方法
                # 示例:D8_A=1 + 在线客服 + 携程-在线 → D8_SQ1_1
                if '_' in original_def and '=' in original_def:
                    # 提取关键信息
                    def_prefix = original_def.split('_')[0]  # D8
                    code_value = original_def.split('=')[1]   # 1
                    
                    # 从维度值提取平台和分类
                    platform = ''
                    category_keywords = [dim_type]  # 一级分类
                    if '-' in dim_value:
                        parts = dim_value.split('-')
                        platform = parts[0]  # 携程/去哪儿
                        if len(parts) > 1:
                            category_keywords.append(parts[1])  # 二级分类
                    else:
                        platform = dim_value
                    
                    # 查找候选变量
                    candidates = []
                    for var_name, var_info in var_data.items():
                        # 条件1:变量名以题号前缀开头
                        if not var_name.startswith(def_prefix):
                            continue
                        
                        label = var_info.get('label', '')
                        score = 0
                        
                        # 条件2:变量标签包含平台名
                        if platform and platform in label:
                            score += 50
                        
                        # 条件3:变量标签包含分类关键词
                        for keyword in category_keywords:
                            if keyword and keyword in label:
                                score += 30
                        
                        # 条件4:code匹配(变量名结尾或标签中)
                        if var_name.endswith(f'_{code_value}') or f'A{code_value}' in var_name:
                            score += 40
                        
                        if score > 0:
                            candidates.append((var_name, score, label))
                    
                    # 选择最佳匹配
                    if candidates:
                        candidates.sort(key=lambda x: x[1], reverse=True)
                        best_match = candidates[0]
                        matched_var = best_match[0]
                        match_type = '自动匹配'
                        confidence = f'{min(best_match[1], 95)}%'
                
                # 第三级:解析题号结构,查找子变量
                # D7_A → 基础题号D7,子题号A
                # Q20_A → Q20 和 A
                if not matched_var:
                    base_match = re.match(r'^(\w+?)(_[A-Z])?$', var_candidate)
                    if base_match:
                        base_code = base_match.group(1)  # D7 或 Q20
                        sub_code = base_match.group(2)   # _A 或 None
                        
                        # 查找所有相关变量
                        matched_vars = {}
                        for var_name, var_info in var_data.items():
                            if base_code in var_name or base_code.upper() in var_name.upper():
                                if sub_code:
                                    # 子题号A可能对应 _1_ 或 A1
                                    sub_letter = sub_code[1]  # A
                                    if f'_{sub_letter}' in var_name or f'_{ord(sub_letter) - ord("A") + 1}_' in var_name:
                                        matched_vars[var_name] = var_info
                                else:
                                    matched_vars[var_name] = var_info
                        
                        if not matched_vars:
                            # 尝试简单的前缀匹配
                            for var_name, var_info in var_data.items():
                                if var_name.startswith(base_code + '_') or var_name.upper().startswith(base_code.upper() + '_'):
                                    matched_vars[var_name] = var_info
                        
                        if matched_vars:
                        # 第三级:用维度值匹配(支持复合维度值如"酒店-携程")
                        best_match = None
                        best_score = 0
                        
                        # 拆分复合维度值
                        dim_parts = dim_value.split('-')
                        
                        for var_name, var_info in matched_vars.items():
                            label = var_info['label']
                            score = 0
                            
                            # 复合维度值匹配:所有部分都在标签中
                            all_parts_found = True
                            for part in dim_parts:
                                if part in label:
                                    score += 50
                                else:
                                    all_parts_found = False
                            
                            if all_parts_found:
                                score += 100
                            
                            # code匹配(=1 匹配 _1 或 A1)
                            if code_value:
                                code_patterns = [
                                    f'_{code_value}_',
                                    f'_{code_value}',
                                    f'A{code_value}',
                                    f'{code_value}_'
                                ]
                                for pattern in code_patterns:
                                    if pattern in var_name:
                                        score += 50
                                        break
                            
                            # 语义一致性验证
                            semantic_keywords = ['平台', '客服', '联系', '问题', '产品', '服务']
                            matched_keywords = [kw for kw in semantic_keywords if kw in label or kw in dim_type]
                            score += len(matched_keywords) * 10
                            
                            if score > best_score:
                                best_score = score
                                best_match = var_name
                        
                        if best_match and best_score >= 150:
                            matched_var = best_match
                            match_type = '自动匹配'
                            confidence = f'{min(best_score, 95):.0f}%'
                        elif best_match and best_score >= 100:
                            matched_var = best_match
                            match_type = '模糊匹配'
                            confidence = f'{min(best_score, 75):.0f}%'
        
        # 设置匹配结果
        req['matched_var'] = matched_var
        req['matched_var_label'] = var_data[matched_var].get('label', '') if matched_var else ''
        req['match_type'] = match_type
        req['confidence'] = confidence
        
        # 4.3 生成数据逻辑定义(修复版 - 支持值标签转换)
        req['logic_def'] = generate_logic_definition(original_def, matched_var, value_data)
    
    # 4.4 生成新变量名和Code
    banner_counters = {}
    
    for req in requirements:
        banner = req['banner']
        dim_type = req['dim_type']
        
        if banner not in banner_counters:
            banner_counters[banner] = {'dim_idx': 0, 'last_dim_type': None}
        
        counter = banner_counters[banner]
        
        if dim_type != counter['last_dim_type']:
            counter['dim_idx'] += 1
            counter['value_idx'] = 1
            counter['last_dim_type'] = dim_type
        else:
            counter['value_idx'] += 1
        
        # 提取banner序号
        banner_num = re.search(r'Banner(\d+)', banner)
        banner_idx = banner_num.group(1) if banner_num else '1'
        
        req['new_var_name'] = f"banner{banner_idx}_{counter['dim_idx']}_{counter['value_idx']}"
        req['code'] = counter['value_idx']
    
    return requirements

Step 5: 质量检查与报告

5.1 完整性检查

def check_completeness(requirements, var_data, value_data):
    """5.1 完整性检查"""
    unmatched = [r for r in requirements if not r.get('matched_var')]
    
    missing_value_labels = []
    for req in requirements:
        var_name = req.get('matched_var')
        if var_name and var_name not in value_data:
            missing_value_labels.append({
                'var_name': var_name,
                'dim_type': req['dim_type']
            })
    
    incomplete_logic = []
    for req in requirements:
        if req.get('logic_def') and '?' in req['logic_def']:
            incomplete_logic.append({
                'dim_type': req['dim_type'],
                'dim_value': req['dim_value'],
                'logic_def': req['logic_def']
            })
    
    return {
        'total_items': len(requirements),
        'unmatched_count': len(unmatched),
        'missing_value_labels': missing_value_labels,
        'incomplete_logic': incomplete_logic
    }

5.2 来源验证

def verify_sources(requirements, var_data, value_data):
    """5.2 来源验证"""
    valid = []
    invalid = []
    manual = []
    
    for req in requirements:
        var_name = req.get('matched_var')
        
        if not var_name:
            manual.append(req)
            continue
        
        if var_name not in var_data:
            invalid.append({'req': req, 'reason': f'变量 {var_name} 不在变量表中'})
            continue
        
        valid.append(req)
    
    return {
        'valid_matches': valid,
        'invalid_matches': invalid,
        'manual_review_items': manual
    }

5.3 匹配率计算

def calculate_match_rate(requirements):
    """5.3 匹配率计算"""
    total = len(requirements)
    
    auto = len([r for r in requirements if r.get('match_type') == '自动匹配'])
    fuzzy = len([r for r in requirements if r.get('match_type') == '模糊匹配'])
    manual = len([r for r in requirements if r.get('match_type') == '需人工审核'])
    
    match_rate = (auto + fuzzy) / total * 100 if total > 0 else 0
    
    return {
        'total': total,
        'auto_matched': auto,
        'fuzzy_matched': fuzzy,
        'manual_review': manual,
        'match_rate': round(match_rate, 2)
    }

5.4 输出文件生成

def generate_review_output(requirements, var_data, output_file):
    """5.4 生成待审核版(v2.1.0修复版)
    
    关键修复:
    1. 变量标签不截断,输出完整内容
    2. 需求信息格式正确:Banner-维度类型-维度值
    3. 包含变量表和值标签表作为参考
    """
    from openpyxl import Workbook
    from openpyxl.styles import Font, PatternFill
    
    wb = Workbook()
    
    # Sheet1: 待审核版
    ws1 = wb.active
    ws1.title = "待审核版"
    
    headers = ['需求信息', '条件1', '条件2', '条件3', '需求定义', '变量名称', '变量标签', 
               '数据逻辑定义', '匹配状态', '置信度']
    
    for col, header in enumerate(headers, 1):
        cell = ws1.cell(1, col, header)
        cell.font = Font(bold=True, color='FFFFFF')
        cell.fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
    
    for row_idx, req in enumerate(requirements, 2):
        # 关键修复:正确的需求信息格式
        demand_info = f"{req['banner']}-{req['dim_type']}-{req['dim_value']}"
        ws1.cell(row_idx, 1, demand_info)
        ws1.cell(row_idx, 2, req['conditions'][0]['value'] if len(req['conditions']) > 0 else '')
        ws1.cell(row_idx, 3, req['conditions'][1]['value'] if len(req['conditions']) > 1 else '')
        ws1.cell(row_idx, 4, req['conditions'][2]['value'] if len(req['conditions']) > 2 else '')
        ws1.cell(row_idx, 5, req.get('demand_def', ''))
        ws1.cell(row_idx, 6, req.get('matched_var', ''))
        
        # 关键修复:不截断标签,输出完整内容
        matched_var = req.get('matched_var')
        if matched_var and matched_var in var_data:
            ws1.cell(row_idx, 7, var_data[matched_var].get('label', ''))
        else:
            ws1.cell(row_idx, 7, req.get('matched_var_label', ''))
        
        ws1.cell(row_idx, 8, req.get('logic_def', ''))
        ws1.cell(row_idx, 9, req.get('match_type', '需人工审核'))
        ws1.cell(row_idx, 10, req.get('confidence', '0%'))
    
    wb.save(output_file)

def generate_final_output(requirements, output_file):
    """5.4 生成最终版"""
    from openpyxl import Workbook
    from openpyxl.styles import Font, PatternFill
    
    wb = Workbook()
    ws = wb.active
    ws.title = "最终版"
    
    # 表头
    headers = ['需求信息', '条件1', '条件2', '条件3', '需求定义', '变量名称', '变量标签',
               '数据逻辑定义', '新变量名', '标签', 'code']
    
    for col, header in enumerate(headers, 1):
        cell = ws.cell(1, col, header)
        cell.font = Font(bold=True, color='FFFFFF')
        cell.fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
    
    # 数据
    for row_idx, req in enumerate(requirements, 2):
        ws.cell(row_idx, 1, f"{req['banner']}-{req['dim_type']}-{req['dim_value']}")
        ws.cell(row_idx, 2, req['conditions'][0]['value'] if len(req['conditions']) > 0 else '')
        ws.cell(row_idx, 3, req['conditions'][1]['value'] if len(req['conditions']) > 1 else '')
        ws.cell(row_idx, 4, req['conditions'][2]['value'] if len(req['conditions']) > 2 else '')
        ws.cell(row_idx, 5, req.get('demand_def', ''))
        ws.cell(row_idx, 6, req.get('matched_var', ''))
        ws.cell(row_idx, 7, req.get('matched_var_label', ''))
        ws.cell(row_idx, 8, req.get('logic_def', ''))
        ws.cell(row_idx, 9, req.get('new_var_name', ''))
        ws.cell(row_idx, 10, req['dim_value'])
        ws.cell(row_idx, 11, req.get('code', ''))
    
    wb.save(output_file)

5.5 处理报告生成

def generate_report(requirements, completeness, verification, match_rate):
    """5.5 生成处理报告"""
    report = f"""# 维度定义处理报告

## 处理摘要
- 处理时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
- 总条目数: {match_rate['total']}
- 自动匹配: {match_rate['auto_matched']} ({match_rate['auto_matched']/match_rate['total']*100:.1f}%)
- 模糊匹配: {match_rate['fuzzy_matched']} ({match_rate['fuzzy_matched']/match_rate['total']*100:.1f}%)
- 需人工审核: {match_rate['manual_review']} ({match_rate['manual_review']/match_rate['total']*100:.1f}%)
- **整体匹配率: {match_rate['match_rate']}%**

## 完整性检查
- 解析条目数: {completeness['total_items']}
- 未匹配变量数: {completeness['unmatched_count']}
- 缺失值标签变量: {len(completeness['missing_value_labels'])}
- 不完整逻辑定义: {len(completeness['incomplete_logic'])}

## 来源验证
- 有效匹配: {len(verification['valid_matches'])}
- 无效匹配: {len(verification['invalid_matches'])}
- 需人工审核: {len(verification['manual_review_items'])}

## 需人工审核项(前20条)
| 序号 | 需求信息 | 维度类型 | 维度值 | 建议操作 |
|:---|:---|:---|:---|:---|
"""
    
    for i, req in enumerate(verification['manual_review_items'][:20], 1):
        report += f"| {i} | {req['banner']}-{req['dim_type']}-{req['dim_value']} | {req['dim_type']} | {req['dim_value']} | 人工指定变量名 |\n"
    
    report += """
## 输出文件
1. **待审核版**: 维度定义表-待审核版.xlsx
2. **最终版**: 维度定义表-最终版.xlsx

## 注意事项
- 请重点审核"需人工审核"的条目
- 确认变量名称是否正确
- 确认数据逻辑定义是否完整
- 建议人工审核后重新生成最终版
"""
    
    return report

使用方法

完整处理流程(含人工审核环节)

┌─────────────────────────────────────────────────────────────────┐
│                    标准处理流程(含人工审核)                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  【第一轮】生成审核文件                                            │
│     ├─ 输入:原始编码表(Banner表 + 变量表 + 值标签表)            │
│     ├─ 执行:Step 1-5 完整流程                                    │
│     └─ 输出:审核文件(3个Sheet)                                  │
│              ├─ Sheet1: 待审核版(需人工审核的内容)               │
│              ├─ Sheet2: 变量表(原始变量定义,供参考)              │
│              └─ Sheet3: 值标签表(原始值标签,供参考)              │
│                          ↓                                      │
│  【人工审核】用户审核并修正                                        │
│     ├─ 审核并修正"变量名称"列                                     │
│     ├─ 审核并修正"数据逻辑定义"列                                 │
│     ├─ 补充缺失信息                                               │
│     └─ 保存为:审核反馈文件                                        │
│                          ↓                                      │
│  【第二轮】生成最终版                                              │
│     ├─ 输入:审核反馈文件                                          │
│     ├─ 执行:读取审核结果,更新匹配,生成最终版                    │
│     └─ 输出:最终版维度定义表                                      │
│              ├─ 包含完整的新变量名、code、标签等                   │
│              └─ 基于审核后的变量名查询变量标签                      │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

为什么需要人工审核?

根据实际项目经验,以下情况必须人工审核

  1. 变量名称匹配不确定

    • 自动匹配可能选择错误的变量
    • 多选题变量(如 Q5__1, Q5__2)需要人工确认
    • 复杂维度(如城市线级、地区划分)需要人工指定变量
  2. 数据逻辑定义需要业务确认

    • "划分"类型的维度需要明确具体逻辑
    • 组合维度需要确认组合规则
    • 范围维度需要展开为具体值
  3. 派生变量不在变量表中

    • 如 D4a(城市级别)可能是派生变量
    • 需要人工指定实际使用的变量名

第一轮:生成审核文件

def generate_review_file(requirements, var_data, value_data, output_file):
    """
    生成审核文件(3个Sheet)
    Sheet1: 待审核版
    Sheet2: 变量表(供参考)
    Sheet3: 值标签表(供参考)
    """
    from openpyxl import Workbook
    from openpyxl.styles import Font, PatternFill
    
    wb = Workbook()
    
    # Sheet1: 待审核版
    ws1 = wb.active
    ws1.title = "待审核版"
    
    headers = ['需求信息', '条件1', '条件2', '条件3', '需求定义', 
               '变量名称', '变量标签', '数据逻辑定义', '匹配状态', '置信度']
    
    for col, header in enumerate(headers, 1):
        cell = ws1.cell(1, col, header)
        cell.font = Font(bold=True, color='FFFFFF')
        cell.fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
    
    for row_idx, req in enumerate(requirements, 2):
        ws1.cell(row_idx, 1, f"{req['banner']}-{req['dim_type']}-{req['dim_value']}")
        ws1.cell(row_idx, 2, req['conditions'][0]['value'] if len(req['conditions']) > 0 else '')
        ws1.cell(row_idx, 3, req['conditions'][1]['value'] if len(req['conditions']) > 1 else '')
        ws1.cell(row_idx, 4, req['conditions'][2]['value'] if len(req['conditions']) > 2 else '')
        ws1.cell(row_idx, 5, req.get('demand_def', ''))
        ws1.cell(row_idx, 6, req.get('matched_var', ''))  # 重点审核列
        ws1.cell(row_idx, 7, req.get('matched_var_label', ''))
        ws1.cell(row_idx, 8, req.get('logic_def', ''))  # 重点审核列
        ws1.cell(row_idx, 9, req.get('match_type', '需人工审核'))
        ws1.cell(row_idx, 10, req.get('confidence', '0%'))
    
    # Sheet2: 变量表(供参考)
    ws2 = wb.create_sheet("变量表")
    ws2.cell(1, 1, "变量名")
    ws2.cell(1, 2, "变量标签")
    for row_idx, (var_name, var_info) in enumerate(var_data.items(), 2):
        ws2.cell(row_idx, 1, var_name)
        ws2.cell(row_idx, 2, var_info.get('label', ''))
    
    # Sheet3: 值标签表(供参考)
    ws3 = wb.create_sheet("值标签表")
    ws3.cell(1, 1, "变量名")
    ws3.cell(1, 2, "Code")
    ws3.cell(1, 3, "标签")
    row_idx = 2
    for var_name, codes in value_data.items():
        for code, label in codes.items():
            ws3.cell(row_idx, 1, var_name)
            ws3.cell(row_idx, 2, code)
            ws3.cell(row_idx, 3, label)
            row_idx += 1
    
    wb.save(output_file)

人工审核要点

审核文件列说明:

列名 说明 审核重点
需求信息 完整需求路径 确认无误
条件1-3 拆分后的条件 确认无误
需求定义 业务定义 参考
变量名称 自动匹配的变量 重点审核
变量标签 变量描述 辅助确认
数据逻辑定义 初步逻辑 重点审核
匹配状态 自动/模糊/需审核 参考
置信度 匹配置信度 参考

审核操作:

  1. 打开审核文件(3个Sheet)
  2. 在"待审核版"Sheet中审核"变量名称"和"数据逻辑定义"列
  3. 参考"变量表"和"值标签表"Sheet确认变量信息
  4. 修正错误的匹配
  5. 补充缺失的变量名
  6. 保存为审核反馈文件

第二轮:人工审核后处理(v2.1.7 新增)

处理流程

  1. 读取人工审核后的文件 - 包含已审核的变量名称
  2. 匹配变量标签 - 根据变量名称从变量表查找对应标签(仅当变量标签列为空时)
  3. 生成数据逻辑定义 - 根据变量名称和值标签生成(仅当数据逻辑定义列为空时)
  4. 保留人工填写内容 - 如果已有内容,保持原样不变

关键规则

  • 变量标签列非空 → 跳过,保留人工填写内容
  • 数据逻辑定义列非空 → 跳过,保留人工填写内容
  • 仅当列为空时,才自动匹配/生成
def process_reviewed_file(review_file, encoding_file, output_file):
    """
    处理人工审核后的文件(v2.1.7 新增)
    
    流程:
    1. 解析原始编码表(获取变量表和值标签表)
    2. 读取人工审核后的文件
    3. 对于每一行:
       - 如果变量标签列为空,根据变量名称匹配变量标签
       - 如果数据逻辑定义列为空,根据变量名称和值标签生成
       - 如果已有内容,保持原样不变
    4. 保存结果
    """
    from openpyxl import load_workbook
    import pandas as pd
    
    # 初始化处理器
    processor = DimensionDefinerPro()
    processor.parse_spss_encoding(encoding_file)
    
    # 构建变量名到变量标签的映射
    var_label_map = dict(zip(
        processor.variables_df['变量名称'], 
        processor.variables_df['变量标签']
    ))
    
    # 读取人工审核后的文件
    wb = load_workbook(review_file)
    ws = wb['需求定义']
    
    # 处理每一行
    updated_var_label = 0
    updated_logic = 0
    skipped = 0
    
    for row in range(2, ws.max_row + 1):
        var_name = ws.cell(row, 6).value  # 变量名称
        existing_var_label = ws.cell(row, 7).value  # 现有变量标签
        existing_logic = ws.cell(row, 8).value  # 现有数据逻辑定义
        definition = ws.cell(row, 5).value  # 需求定义
        dim_value = ws.cell(row, 3).value  # 条件2 (dim_value)
        
        if not var_name:
            continue
        
        # 1. 匹配变量标签(如果为空)
        if not existing_var_label and var_name in var_label_map:
            ws.cell(row, 7).value = var_label_map[var_name]
            updated_var_label += 1
        
        # 2. 生成数据逻辑定义(如果为空且有需求定义)
        if not existing_logic and definition:
            data_logic = processor._generate_data_logic(
                var_name, definition, dim_value or ''
            )
            if data_logic:
                ws.cell(row, 8).value = data_logic
                updated_logic += 1
        
        if existing_var_label or existing_logic:
            skipped += 1
    
    # 保存结果
    wb.save(output_file)
    
    return {
        'updated_var_label': updated_var_label,
        'updated_logic': updated_logic,
        'skipped': skipped
    }

处理示例

变量名称 原变量标签 处理后 原数据逻辑定义 处理后
H1 (空) H1_城市级别映射关系... (空) H1=一线城市
D10 (空) D10_您在工作或生活中... (空) D10=我不知道什么是AI工具...
D6_2 人工填写 保持不变 (空) D6_2=是
D8_SQ1_99 人工填写 保持不变 人工填写 保持不变

第二轮(旧版):生成最终版

def generate_final_from_review(review_file, output_file):
    """
    基于审核反馈文件生成最终版(旧版,已弃用)
    """
    from openpyxl import load_workbook
    
    # 读取审核结果
    wb = load_workbook(review_file)
    ws = wb['待审核版']
    
    requirements = []
    for row in ws.iter_rows(min_row=2, values_only=True):
        req = {
            'demand_info': row[0],
            'condition1': row[1],
            'condition2': row[2],
            'condition3': row[3],
            'demand_def': row[4],
            'matched_var': row[5],  # 使用审核后的变量名
            'var_label': row[6],
            'logic_def': row[7],  # 使用审核后的逻辑定义
            'match_type': row[8],
            'confidence': row[9]
        }
        requirements.append(req)
    
    # 生成新变量名和code
    banner_counters = {}
    for req in requirements:
        # 解析banner信息
        banner_match = re.search(r'(Banner\d+)', req['demand_info'])
        banner = banner_match.group(1) if banner_match else 'Banner1'
        
        if banner not in banner_counters:
            banner_counters[banner] = {'dim_idx': 0, 'last_cond': None}
        
        counter = banner_counters[banner]
        current_cond = req['condition1']
        
        if current_cond != counter['last_cond']:
            counter['dim_idx'] += 1
            counter['value_idx'] = 1
            counter['last_cond'] = current_cond
        else:
            counter['value_idx'] += 1
        
        banner_idx = re.search(r'\d+', banner).group()
        req['new_var_name'] = f"banner{banner_idx}_{counter['dim_idx']}_{counter['value_idx']}"
        req['code'] = counter['value_idx']
        req['label'] = req['condition2'] if req['condition2'] else req['condition1']
    
    # 生成最终版Excel
    wb_out = Workbook()
    ws_out = wb_out.active
    ws_out.title = "最终版"
    
    headers = ['需求信息', '条件1', '条件2', '条件3', '需求定义', 
               '变量名称', '变量标签', '数据逻辑定义', '新变量名', '标签', 'code']
    
    for col, header in enumerate(headers, 1):
        cell = ws_out.cell(1, col, header)
        cell.font = Font(bold=True, color='FFFFFF')
        cell.fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
    
    for row_idx, req in enumerate(requirements, 2):
        ws_out.cell(row_idx, 1, req['demand_info'])
        ws_out.cell(row_idx, 2, req['condition1'])
        ws_out.cell(row_idx, 3, req['condition2'])
        ws_out.cell(row_idx, 4, req['condition3'])
        ws_out.cell(row_idx, 5, req['demand_def'])
        ws_out.cell(row_idx, 6, req['matched_var'])
        ws_out.cell(row_idx, 7, req['var_label'])
        ws_out.cell(row_idx, 8, req['logic_def'])
        ws_out.cell(row_idx, 9, req['new_var_name'])
        ws_out.cell(row_idx, 10, req['label'])
        ws_out.cell(row_idx, 11, req['code'])
    
    wb_out.save(output_file)

完整处理流程代码

# 主函数
def main():
    input_file = '输入文件.xlsx'
    output_prefix = '维度定义表'
    
    print("=" * 60)
    print("dimension-definer-pro 维度定义处理")
    print("=" * 60)
    
    # Step 1: 格式识别与解析
    print("\n[Step 1] 格式识别与解析...")
    banner_data, var_data, value_data = step1_parse_files(input_file)
    
    # Step 2: 数据清洗与标准化
    print("\n[Step 2] 数据清洗与标准化...")
    banner_data, var_data, value_data = step2_clean_data(banner_data, var_data, value_data)
    
    # Step 3: 数据整理
    print("\n[Step 3] 数据整理...")
    requirements = step3_organize_data(banner_data)
    
    # Step 4: 维度匹配与定义生成
    print("\n[Step 4] 维度匹配与定义生成...")
    requirements = step4_match_dimensions(requirements, var_data, value_data)
    
    # Step 5: 质量检查与报告
    print("\n[Step 5] 质量检查与报告生成...")
    completeness = check_completeness(requirements, var_data, value_data)
    verification = verify_sources(requirements, var_data, value_data)
    match_rate = calculate_match_rate(requirements)
    
    # 5.4 输出审核文件(3个Sheet)
    print("  生成审核文件(含待审核版+变量表+值标签表)...")
    generate_review_file(requirements, var_data, value_data, 
                         f"{output_prefix}-审核版.xlsx")
    
    # 生成报告
    report = generate_report(requirements, completeness, verification, match_rate)
    with open(f"{output_prefix}-处理报告.md", 'w', encoding='utf-8') as f:
        f.write(report)
    
    print("\n" + "=" * 60)
    print(f"第一轮处理完成!")
    print(f"  审核文件: {output_prefix}-审核版.xlsx")
    print(f"  处理报告: {output_prefix}-处理报告.md")
    print(f"  整体匹配率: {match_rate['match_rate']}%")
    print("=" * 60)
    print("\n请审核后发送反馈文件,我将生成最终版。")

# 第二轮:基于审核反馈生成最终版
def main_final(review_file, output_prefix):
    """基于审核反馈生成最终版"""
    print("=" * 60)
    print("dimension-definer-pro 生成最终版")
    print("=" * 60)
    
    print(f"\n读取审核文件: {review_file}")
    generate_final_from_review(review_file, f"{output_prefix}-最终版.xlsx")
    
    print("\n" + "=" * 60)
    print(f"最终版生成完成!")
    print(f"  最终版: {output_prefix}-最终版.xlsx")
    print("=" * 60)

输入文件要求

必需的工作表

Sheet名称 说明 必需
Banner 表头需求定义
变量 SPSS变量表
值标签 SPSS值标签表

Banner表结构

行1: Banner名称(如"Banner1-人口学")
行2: 空行
行3: Total | 维度类型1 | 维度类型2 | ...
行4: 空行
行5: 维度值1 | 维度值2 | ...(同时也是Definition)
行6: Definition1 | Definition2 | ...

变量表结构(SPSS格式)

│名称                │位置│标签                                                │...
├────────────────────┼────┼────────────────────────────────────────────────────┤
│序号                │   1│序号                                                │...
│VAR_A               │   2│完成状态                                            │...
│D2                  │  15│D2_您的性别是                                       │...

值标签表结构(SPSS格式)

│Variable            │Value│Label                                               │...
├────────────────────┼─────┼────────────────────────────────────────────────────┤
│D2                  │    1│男性                                                │...
│                    │    2│女性                                                │...

输出文件格式

待审核版

列名 说明
需求信息 Banner-维度类型-维度值
条件1-3 拆分后的条件
需求定义 业务定义
变量名称 自动匹配的变量名
变量标签 变量描述
数据逻辑定义 初步逻辑定义
匹配状态 自动匹配/模糊匹配/需人工审核
置信度 匹配置信度

最终版

列名 说明
需求信息 Banner-维度类型-维度值
条件1-3 拆分后的条件
需求定义 业务定义
变量名称 审核后的变量名
变量标签 变量描述
数据逻辑定义 完整逻辑定义
新变量名 banner{序号}{维度序号}{值序号}
标签 维度值标签
code 每个维度内从1递增

更新日志

v2.1.3 (2026-03-30)

值标签解析完整性修复 - 关键修复

问题8: 值标签表解析不完整(关键修复)

  • 根因1:正则表达式 (\d+\.?\d*) 无法匹配 .00 格式(如 .00 否
  • 根因2:依赖分隔线(├─)判断变量分组,但文件中很多变量连续排列无分隔线
  • 解决1:改进正则为 ((?:\d+)?\.\d+),支持可选数字前缀的小数
  • 解决2:通过变量名存在性判断新变量开始,不依赖分隔线
  • 效果:变量数量从 96个 → 692个(+620%,完整提取所有变量)
  • 示例:
    • D1_A1变量:.00 否 | 1.00 是(之前完全遗漏)✓
    • 触点变量:48个值标签(之前只提取4个)✓
  • 函数:parse_value_sheet_fixed() v2.1.3修复版

v2.1.0 (2026-03-27)

重大修复版本 - 修复3个核心问题

问题1: Banner解析不完整(关键修复)

  • 根因:错误理解Total行结构,将Total行的下一行当成维度类型行
  • 解决:Total行(行26)同时是维度类型行,添加前向填充逻辑
  • 效果:从部分Banner输出 → 完整13个Banner(195条→138条正确解析)
  • 更新函数:parse_banner_sheet_v3()

问题2: 需求信息格式错误(关键修复)

  • 根因:混淆维度类型和维度值,导致"酒店-携程-酒店-携程"错误格式
  • 解决:正确解析三行结构(行26类型/行27值/行28Definition)
  • 效果:正确格式"Banner5-平台服务体验-经服业务线-携程-酒店-携程"

问题3: 变量标签截断(关键修复)

  • 根因:代码中有[:100]截断标签
  • 解决:移除截断,输出完整标签(支持200+字符)
  • 更新函数:generate_review_output()

问题4: 值标签表输出不完整

  • 根因:code行变量名为空时未继承上一个变量名
  • 解决:使用current_var变量跟踪确保code正确关联
  • 效果:从3个变量→570个变量,1349个code全部正确解析
  • 函数:parse_value_sheet_fixed()

问题5: 匹配率低(重要改进)

  • 根因:只支持简单变量匹配
  • 解决:新增多种匹配策略
    • 子变量匹配(D6=1→D6_1)
    • 复合维度值匹配("酒店-携程"→D7_1_1)
    • 三级题号匹配(D7_A=1→D7_1_1)
    • 语义一致性验证
  • 效果:匹配率从27.54%提升到78.26%(+50.72%)
  • 函数:step4_match_dimensions()

问题6: 多级嵌套题号匹配(v2.1.1新增)

  • 根因:无法匹配 D8_A=1 → D8_SQ1_1 这种多级嵌套结构
  • 解决:新增基于多维度信息交叉验证的通用匹配方法
    • 提取题号前缀(D8)
    • 提取一级分类(在线客服/电话客服)
    • 从维度值提取平台和二级分类(携程-在线 → 平台=携程, 分类=在线)
    • 多维度交叉验证:题号前缀 + 平台名 + 分类关键词 + code
  • 效果:支持 Banner7 等复杂嵌套结构匹配
  • 示例:
    • D8_A=1 + 在线客服 + 携程-在线 → D8_SQ1_1 ✓
    • D8_B=1 + 在线客服 + 去哪儿-在线 → D8_SQ2_1 ✓
    • D8_A=2 + 电话客服 + 携程-电话 → D8_SQ1_2 ✓
  • 函数:step4_match_dimensions() 新增第二级通用匹配

问题7: 数据逻辑定义输出错误(v2.1.2新增)

  • 根因:数据逻辑定义直接输出原始definition,未转换为中文标签
  • 解决:新增 generate_logic_definition() 函数
    • 从值标签表查找code对应的中文标签
    • 支持 / 转换为"或",, 转换为"且"
    • 支持多选题输出(如 D7_5_3=是)
  • 效果:
    • D2=1 → D2=男性 ✓
    • D3a=3/4 → D3a=25-29岁或D3a=30-34岁 ✓
    • D7_E=3 → D7_5_3=是 ✓
  • 函数:generate_logic_definition() 新增

v2.0.0 (2026-03-27)

  • 重构为5步标准化处理流程
  • 添加完整的Step 1-5详细说明
  • 支持混合结构Banner表解析
  • 优化变量名提取逻辑(从Definition)
  • 完善质量检查和报告生成
  • 添加完整的代码示例

v1.3.0 (2026-03-26)

  • 添加人工审核流程规范
  • 明确两轮处理机制(review + final)
  • 完善输出格式规范

v1.0.0 (2026-03-26)

  • 初始版本
Installs
1
First Seen
Apr 3, 2026