如何使用Python复现SAS输出含特殊行的定宽格式文本文件
定宽文件生成实现方案
不用强行寻找pandas内置的to_fwf方法,自定义逐行拼接写入的方案灵活度更高,完全适配你提的所有规则,具体实现思路如下:
前置准备
提前明确每个输出部分的字段规则:包括每个字段的宽度、对齐方式、数据类型(比如数值是否补0、字符串是否截断补空格),可以用Python格式化语法提前定义好各部分的模板,定宽规则全部在模板里控制即可。
实现步骤
- 先保证原始数据框的顺序已经符合你的要求,后续全程不做打乱顺序的操作
- 按
VAR1对数据框分组,分组时指定sort=False,保证分组顺序和原数据中VAR1的出现顺序完全一致 - 初始化空列表存储所有待输出的行,先写入开头指定标识行
- 遍历每个
VAR1分组:- 每个分组只输出一次FIRST、SECOND部分的行,按模板格式化后加入输出列表
- 过滤当前分组内
SEQ≤3的记录,最多取前3条,序号从01开始计数 - 遍历过滤后的有效记录:
- 按模板拼接THIRD部分的行,开头补上当前两位序号,加入输出列表
- 检查当前记录
VAR6是否非空,非空则按模板拼接FOURTH部分的行,开头补上相同的两位序号,加入输出列表 - 序号自增,到03后停止遍历
- 所有分组处理完成后,加入结尾指定标识行
- 直接用Python内置的文件写入方法,把所有输出行逐行写入文件即可
示例代码
import pandas as pd # 此处替换为你自己的原始数据集,提前保证数据顺序符合要求 df = pd.read_csv("your_source_data.csv") # 以下所有模板的字段、宽度、对齐规则都可以按需修改 # 示例模板说明:< 表示左对齐,> 表示右对齐,数字表示占用宽度,.2f表示保留2位小数 FIRST_TPL = "F{:<20}{:<15}{:>8}" SECOND_TPL = "S{:<20}{:<18}{:>10.2f}" THIRD_TPL = "{:02d}T{:<12}{:<10}{:>6d}" FOURTH_TPL = "{:02d}F{:<30}" # 首尾指定标识行,按需替换为实际值 HEAD_LINE = "HEAD20240001" TAIL_LINE = "TAIL20240001" output_lines = [HEAD_LINE] # 按VAR1分组,不排序保留原始顺序 for var1_val, group in df.groupby("VAR1", sort=False): # 写入FIRST、SECOND部分,每个VAR1仅写一次 first_line = FIRST_TPL.format(group["VAR1"].iloc[0], group["VAR2"].iloc[0], group["VAR3"].iloc[0]) output_lines.append(first_line) second_line = SECOND_TPL.format(group["VAR1"].iloc[0], group["VAR4"].iloc[0], group["VAR5"].iloc[0]) output_lines.append(second_line) # 过滤SEQ≤3的记录,最多取前3条 valid_records = group[group["SEQ"] <=3].head(3).reset_index(drop=True) for idx, row in valid_records.iterrows(): seq = idx + 1 # 写入THIRD部分 third_line = THIRD_TPL.format(seq, row["VAR4"], row["VAR5"], row["SEQ"]) output_lines.append(third_line) # VAR6非空时写入FOURTH部分 if pd.notna(row["VAR6"]): fourth_line = FOURTH_TPL.format(seq, row["VAR6"]) output_lines.append(fourth_line) # 写入结尾标识 output_lines.append(TAIL_LINE) # 输出到文件,编码按需调整为gbk/utf-8等 with open("output.fwf", "w", encoding="gbk") as f: for line in output_lines: f.write(line + "\n")
内容的提问来源于stack exchange,提问作者Peter Chen
相关产品推荐
相关产品推荐

