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

如何以最具Pythonic风格生成、清理并保存多组逐元素数组数据?(pandas/numpy)

问题描述

我正在编写Python脚本运行外部进程并收集数据:

  • 有n个输入值,每个值要在m个不同参数值下测试
  • 每对(输入值,参数值)组合,需要从外部接口收集5个变量:var_a到var_e
  • 每组组合必须先写入值到外部接口,再读取响应,只能循环逐点收集
  • 目标是为每个变量返回一个覆盖n×m输入空间的pandas DataFrame,无效数据存为nan

初始框架代码如下:

import numpy as np
import pandas as pd

def run_test(inputs, parameters):
    
    """
    TODO#1: Initialise data structures.
    """

    for n in inputs:
            set_input(n)  # Write value to external interface.

            """
            TODO#2: Clear previous data (important as default should be nan).
            """

            for m in parameters:
                set_parameter(m) # Write value to external interface.
                
                # Read data (from external interface).
                var_a, var_b, var_c = read_var_abc() 
                var_d, var_e = read_var_de()

                # Store values.
               """
               TODO#3: Store current values of each var for this parameter value.
               """
            
            # Save recorded data.
            """
            TODO#4: Store a column of data for each var to its dataframe.
            """

    return dataframes

我希望找到最优雅、Pythonic的实现方式,要求通用(可添加更多变量),避免重复写var_x_array[i] = var_x这类代码。我尝试了两种方案:

方案1:维护当前数据数组的引用列表

为每个变量创建np.array,用列表存储数组引用,同时维护对应DataFrame列表,循环逐列填充:

import numpy as np
import pandas as pd

def run_test(inputs, parameters):
    """
    TODO#1: Initialise data structures.
    """
    var_a, var_b, var_c, var_d, var_e = (np.empty(len(parameters)) for _ in range(5))
    variables = [var_a, var_b, var_c, var_d, var_e]  # List of references to mutable arrays.
    dataframes = [pd.DataFrame(index=parameters, columns=inputs) for _ in variables]

    for n in inputs:
            set_input(n) # Write value to external interface.

            """
            TODO#2: Clear previous data (important as default should be nan).
            """
            for v in variables:
                v.fill(np.nan)


            for i,m in enumerate(parameters):
                set_parameter(m) # Write value to external interface.
                
                # Read data (from external interface) AND store values.
                """
                TODO#3: Store current values of each var for this parameter value.
                """
                var_a[i], var_b[i], var_c[i] = read_var_abc() 
                var_d[i], var_e[i] = read_var_de()
            
            # Save recorded data.
            """
            TODO#4: Store a column of data for each var to its dataframe.
            """
            for i,v in enumerate(variables):
                dataframes[i][n] = v  # Fill column for input 'n' in the 'i'-th DataFrame

    return dataframes # List of DataFrames.

优点

  • 遍历variables即可轻松清理和存储数据

缺点

  • 添加新变量时操作繁琐,需要手动新增数组和列表元素
  • 返回的DataFrame列表顺序不明确,调用者需自行对应变量

方案2:使用字典存储当前数据数组与DataFrame

用字典存储数组和DataFrame,通过键名明确变量对应关系:

def run_test(inputs, parameters):
    """
    TODO#1: Initialise data structures.
    """
    var_names = ["var_a", "var_b", "var_c", "var_d", "var_e"]  
    dataframes = {v: pd.DataFrame(index=parameters, columns=inputs) for v in var_names}
    data = {v: np.empty(len(parameters)) for v in var_names}

    for n in inputs:
            set_input(n) # Write value to external interface.

            """
            TODO#2: Clear previous data (important as default should be nan).
            """
            for array in data.values():
                array.fill(np.nan)

            for i, m in enumerate(parameters):
                set_parameter(m) # Write value to external interface.
                
                # Read data (from external interface).
                """
                TODO#3: Store current values of each var for this parameter value.
                """
                data['var_a'][i], data['var_b'][i], data['var_c'][i] = read_var_abc()
                data['var_d'][i], data['var_e'][i] = read_var_de()
            
            # Save recorded data.
            """
            TODO#4: Store a column of data for each var to its dataframe.
            """
            for v in var_names:
                dataframes[v][n] = data[v]


    return dataframes # Dict of str:DataFrame pairs.

优点

  • 返回的字典通过键名清晰对应每个变量的DataFrame,可读性强

缺点

  • 手动管理字符串变量名,尤其是读取数据时需要逐个赋值,不够灵活
  • 代码略显冗余

我最不满意的是TODO#3部分的写法,曾考虑创建局部变量再填充字典,但除了locals()想不到其他迭代方式,而这种方式不够优雅。请问哪种方案更优?或者有什么更好的实现思路?


优化方案推荐

推荐基于字典结构做进一步优化,解决TODO#3的冗余问题,同时保持扩展性:

import numpy as np
import pandas as pd

def run_test(inputs, parameters):
    # 定义变量名与读取函数的映射,方便扩展
    var_specs = [
        ("var_a", "var_b", "var_c", read_var_abc),
        ("var_d", "var_e", read_var_de)
    ]
    # 提取所有变量名
    var_names = [name for group in var_specs for name in group[:-1]]
    
    # 初始化数据存储结构
    data = {v: np.full(len(parameters), np.nan) for v in var_names}
    dataframes = {v: pd.DataFrame(index=parameters, columns=inputs) for v in var_names}

    for input_val in inputs:
        set_input(input_val)
        
        # 重置当前输入对应的参数数据为nan
        for arr in data.values():
            arr.fill(np.nan)
            
        for param_idx, param_val in enumerate(parameters):
            set_parameter(param_val)
            
            # 批量读取并赋值
            for *names, reader in var_specs:
                values = reader()
                for name, val in zip(names, values):
                    data[name][param_idx] = val
        
        # 将当前输入的所有变量数据写入DataFrame
        for var_name in var_names:
            dataframes[var_name][input_val] = data[var_name]
    
    return dataframes

优势

  1. 扩展性极强:新增变量时只需在var_specs中添加一组(变量名, 读取函数),无需修改其他逻辑
  2. 消除冗余赋值:通过zip批量绑定变量名和读取值,避免手动写data['var_x'][i] = val
  3. 语义清晰:var_specs明确了哪些变量由哪个函数读取,代码可读性高
  4. 保持字典输出的优点:调用者可以通过变量名直接获取对应DataFrame,无需记忆顺序

内容的提问来源于stack exchange,提问作者almnz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:47:18