全国税收调查数据的 .dta 文件中变量名为 f2, f3, ... f295 等编号,不含中文说明。本流程从变量说明文件(Excel或PDF)中提取中文标签,生成 Stata label var 命令,应用到 .dta 文件。
| 年份 | 说明文件格式 | 行号所在列 | 标签列 | 合并单元格逻辑 |
|---|---|---|---|---|
| 2012 | Excel (.xlsx) | E列(5) | B(2)/C(3)/D(4) | C+D合并→取C/D值;否则取D列 |
| 2013 | Excel (.xlsx) | E列(5) | B(2)/C(3)/D(4) | C+D合并→取C/D值;否则取D列 |
| 2014 | Excel (.xlsx) | E列(5) | B(2)/C(3)/D(4) | C+D合并→取C/D值;否则取D列 |
| 2015 | Excel (.xlsx) | F列(6) | C(3)/D(4)/E(5) | D+E合并→取D/E值;否则取E列 |
| 2016 | - | - | 手动/OCR提取 |
关键发现:pandas 的 read_excel 无法识别合并单元格,会导致标签提取错误。必须使用 openpyxl 库处理。
pip install openpyxlExcel中标签列常有合并单元格,例如:
- C列是大分类标题(如"营业利润的计算"),纵向合并多行
- D+E列横向合并,包含具体变量描述(如"营业收入(269=270+271)")
提取规则(以2015年C/D/E列为例,2012-2014年B/C/D列同理):
- C、D、E三列合并成同一个范围 → 取该合并单元格的值
- D、E合并但C是不同范围(C通常是纵向大分类) → 取D/E合并单元格的值(这才是具体变量描述)
- 三列都没合并 → 取最右列(2015年取E列,2012-2014年取D列)
# 2012-2014年
python3 extract_2012_2014_labels_merged.py
# 2015年
python3 extract_2015_labels_merged.py脚本会生成:
{年份}_variable_mapping_merged.txt— 变量映射表{年份}_stata_labels_merged.do— Stata标签do文件
import openpyxl
import re
wb = openpyxl.load_workbook(excel_file, data_only=True)
ws = wb.active
merged_ranges = list(ws.merged_cells.ranges)
def get_merged_range(cell_row, cell_col):
for mr in merged_ranges:
if cell_row >= mr.min_row and cell_row <= mr.max_row \
and cell_col >= mr.min_col and cell_col <= mr.max_col:
return mr
return None
def get_description_for_row(ws, excel_row, label_cols, merged_ranges):
"""
label_cols: 2012-2014为[2,3,4](B/C/D),2015为[3,4,5](C/D/E)
"""
col_b, col_c, col_d = label_cols # 逻辑上的左/中/右三列
mr_b = get_merged_range(excel_row, col_b)
mr_c = get_merged_range(excel_row, col_c)
mr_d = get_merged_range(excel_row, col_d)
# 情况1:三列合并成同一个范围
if mr_b and mr_c and mr_d and mr_b == mr_c == mr_d:
return ws.cell(row=mr_b.min_row, column=mr_b.min_col).value
# 情况2:中间+右侧列合并(最常见的情况)
if mr_c and mr_d and mr_c == mr_d:
return ws.cell(row=mr_c.min_row, column=mr_c.min_col).value
# 情况3:都没合并,取最右列
val = ws.cell(row=excel_row, column=col_d).value
return val if val else ws.cell(row=excel_row, column=col_c).value2016年变量说明为PDF格式,无法用openpyxl处理。需要:
- 用OCR工具或手动方式从PDF提取变量编号和中文描述
- 生成
2016_stata_labels_from_pdf.do文件 - PDF标签末尾常带"全年累计数或期初、期末数"后缀,属于格式残留,可按需清理
* 应用变量标签
clear all
set more off
global data_dir "数据目录路径"
global labels_dir "标签do文件目录"
* 处理某年数据
use "$data_dir/XXXXsd.dta", clear
do "$labels_dir/XXXX_stata_labels_merged.do"
save "$data_dir/XXXXsd_labeled.dta", replace/Applications/Stata/StataMP.app/Contents/MacOS/stata-mp -b do apply_labels.do在Stata中运行 describe 命令检查:
describe f2 f3 f269 f271 f272标签文本中若包含中文双引号(如 ""管理费用""),会导致Stata label var 命令语法错误(r(198))。解决方法:在生成do文件时移除标签中的双引号,而非转义。
Stata变量标签最长80字符(UTF-8下中文约26个字),超长标签会被自动截断。
同一编号在不同年份含义可能不同。例如:
- f269:2012年=税率(25%),2013年=工资,2014/2015年=营业收入
- f127:2012年=已纳城镇土地使用税税额,2013年=已纳房产税税额,2014/2015年=土地面积合计
切勿跨年份直接复制标签!
| 文件 | 说明 |
|---|---|
extract_2012_2014_labels_merged.py |
2012-2014年标签提取脚本(openpyxl,正确处理合并单元格) |
extract_2015_labels_merged.py |
2015年标签提取脚本(openpyxl,正确处理合并单元格) |
2012_stata_labels_merged.do |
2012年Stata标签命令 |
2013_stata_labels_merged.do |
2013年Stata标签命令 |
2014_stata_labels_merged.do |
2014年Stata标签命令 |
2015_stata_labels_merged.do |
2015年Stata标签命令 |
2016_stata_labels_from_pdf.do |
2016年Stata标签命令(PDF来源) |
- 原始数据:
{数据目录}/XXXXsd.dta - 标注后数据:
{数据目录}/XXXXsd_labeled.dta - Excel说明文件:
{数据目录}/税调变量说明07-16/XXXX年企业数据表.xlsx