You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python读取OPL数据文本文件变量并转为numpy数组或DataFrame?

读取OPL格式文本文件并转换为NumPy数组/Pandas DataFrame

针对批量处理多个结构一致的OPL格式.txt文件需求,下面提供一套Python解析方案,能将文件中的set、param等元素分别转换为NumPy数组或Pandas DataFrame。

核心解析思路

OPL数据文件的典型特征:

  • 注释行以#开头,需过滤
  • set定义格式:set 变量名:= 空格分隔的数值;
  • param分三类:
    1. 无索引列表(如示例中的D):直接是多行数值,以;结尾
    2. 带索引一维参数(如示例中的Q):每行是索引 值,以;结尾
    3. 二维参数(如示例中的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:51:09