如何用Python读取OPL数据文本文件变量并转为numpy数组或DataFrame?
读取OPL格式文本文件并转换为NumPy数组/Pandas DataFrame
针对批量处理多个结构一致的OPL格式.txt文件需求,下面提供一套Python解析方案,能将文件中的set、param等元素分别转换为NumPy数组或Pandas DataFrame。
核心解析思路
OPL数据文件的典型特征:
- 注释行以
#开头,需过滤 set定义格式:set 变量名:= 空格分隔的数值;param分三类:- 无索引列表(如示例中的
D):直接是多行数值,以;结尾 - 带索引一维参数(如示例中的
Q):每行是索引 值,以;结尾 - 二维参数(如示例中的
c[*,*]):先有表头行,后续每行是行索引 + 列值,以;结尾
- 无索引列表(如示例中的
完整实现代码
import re import numpy as np import pandas as pd import os def parse_opl_file(file_path): # 读取文件并预处理:过滤注释、空行,合并连续空格 with open(file_path, 'r', encoding='utf-8') as f: lines = [ re.sub(r'\s+', ' ', line.strip()) for line in f if not line.strip().startswith('#') and line.strip() ] parsed_data = {} current_block = None block_content = [] for line in lines: # 匹配set定义 set_match = re.match(r'set (\w+):=', line) if set_match: values = line.split(':=')[1].strip().rstrip(';').split() parsed_data[set_match.group(1)] = np.array(values, dtype=int) continue # 匹配param定义(含二维参数) param_match = re.match(r'param (\w+)(?:\[\*,\*\])?:', line) if param_match: param_name = param_match.group(1) # 处理二维param(带[*,*]标记) if '[*,*]' in line: current_block = ('param_2d', param_name) parsed_data[param_name] = {'columns': [], 'rows': []} continue # 处理一维param current_block = ('param', param_name) block_content = [] # 检查当前行是否直接包含值 if ':=' in line: values_part = line.split(':=')[1].strip().rstrip(';') if values_part: block_content.append(values_part) _process_param_block(current_block, block_content, parsed_data) current_block = None block_content = [] continue # 处理块内容行(非定义行) if current_block: if line.endswith(';'): line = line.rstrip(';').strip() if line: block_content.append(line) # 处理二维param的表头 if current_block[0] == 'param_2d' and not parsed_data[current_block[1]]['columns']: parsed_data[current_block[1]]['columns'] = line.split() else: # 处理一维或二维参数的内容 if current_block[0] == 'param': _process_param_block(current_block, block_content, parsed_data) elif current_block[0] == 'param_2d': parsed_data[current_block[1]]['rows'].extend([row.split() for row in block_content]) # 转换为DataFrame df = pd.DataFrame( parsed_data[current_block[1]]['rows'], columns=['row_idx'] + parsed_data[current_block[1]]['columns'] ) df.set_index('row_idx', inplace=True) df = df.astype(int) parsed_data[current_block[1]] = df current_block = None block_content = [] else: block_content.append(line) return parsed_data def _process_param_block(block_info, content, parsed_dict): """辅助函数:处理一维param块""" param_type, param_name = block_info rows = [row.split() for row in content] if all(len(row) == 2 for row in rows): # 带索引的一维param(如Q) idx, vals = zip(*rows) parsed_dict[param_name] = pd.Series(np.array(vals, dtype=int), index=np.array(idx, dtype=int)) else: # 无索引列表(如D) parsed_dict[param_name] = np.array([val for row in rows for val in row], dtype=int) def batch_process_opl_files(folder_path): """批量处理指定文件夹下的所有OPL格式.txt文件""" results = {} for filename in os.listdir(folder_path): if filename.endswith('.txt'): file_path = os.path.join(folder_path, filename) results[filename] = parse_opl_file(file_path) return results # 测试示例(取消注释即可运行) # parsed = parse_opl_file('example_opl.txt') # print("Set K:", parsed['K']) # print("Param Q:\n", parsed['Q']) # print("Param D:", parsed['D']) # print("Param c:\n", parsed['c'])
代码说明
- 预处理阶段:过滤注释和空行,统一空格格式,避免解析干扰
- set解析:直接提取数值转为整数NumPy数组
- param解析:
- 无索引列表(如
D):扁平化后转为NumPy数组 - 带索引一维参数(如
Q):转为Pandas Series,保留索引与值的对应关系 - 二维参数(如
c):转为Pandas DataFrame,行/列索引与原文件完全一致
- 无索引列表(如
- 批量处理:遍历指定文件夹下所有.txt文件,返回以文件名为键的解析结果字典
内容的提问来源于stack exchange,提问作者Gonzalo Luarte
相关产品推荐
相关产品推荐

