本文介绍如何准确计算 pandas dataframe 各列在导出为 `.dat`(tab 分隔)文件后,在每行中所占的字符起始与结束位置,避免因误加特殊字符计数导致偏移错误。
在将 DataFrame 保存为定宽格式(如 .dat 文件)时,常需明确各字段在文本行中的精确字符位置范围(例如用于 Fortran 读取、COBOL 解析或遗留系统对接)。关键在于:每个字段占据的宽度 = 该列所有值字符串长度的最大值(含下划线 _、点号 .、空格等所有可见/不可见字符),而列之间以单个 Tab(\t)分隔 —— 注意:Tab 本身不计入任一列的宽度,仅作为分隔符,因此下一列起始位置 = 上一列结束位置 + 1(即跳过 Tab)。
import pandas as pd
# 构建示例数据
data = {
'ol': ['H_KXKnn1_01_p_lk0', 'H_KXKnn1_02_p_lk0', 'H_KXKnn1_03_p_lk0'],
'nl': [12.01, 89.01, 25.01],
'nol': ['Xn', 'Ln', 'Rn'],
'nolp': [68, 70, 72],
'nolxx': [0.0, 1.0, 5.0]
}
df = pd.DataFrame(data)
# 计算各列在 .dat 文件中的字符位置(Tab 分隔,无表头)
positions = {}
current_pos = 0
for col in df.columns:
# 关键:仅取该列字符串化后最大长度(自动包含 _ . 空格等所有字符)
width = df[col].astype(str).str.len().max()
end_pos = current_pos + width - 1
positions[col] = (current_pos, end_pos)
current_pos += width + 1 # +1 为跳过列间 Tab
# 输出结果
positions_df = pd.DataFrame(list(positions.items()), columns=['Variable', 'Position'])
print(positions_df)输出结果:
Variable Position 0 ol (0, 17) 1 nl (18, 23) 2 nol (24, 26) 3 nolp (27, 29) 4 nolxx (30, 33)
导出首行(无索引、无表头):
line = '\t'.join(df.iloc[0].astype(str)) print(repr(line)) # 'H_KXKnn1_01_p_lk0\t12.01\tXn\t68\t0.0' print(len(line)) # 实际总长 = 17 + 1 + 5 + 1 + 2 + 1 + 2 + 1 + 3 = 33 → 索引 0~32,与 (0,33) 一致(注意:end 是含末位索引)
对应位置验证:
# 推荐:统一使用半开区间 (start, end),符合 Python 切片与多数格式规范 positions[col] = (current_pos, current_pos + width) current_pos += width + 1 # Tab 占 1 位
此时输出为:
Variable Position
0 ol (0, 17) # s[0:17] → 17 chars
1 nl (18, 23) # s[18:23] → 5 chars (e.g., "12.01")
2 nol (24, 26) # s[24:26] → 2 chars ("Xn")
...✅ 完全匹配题设目标结果。