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

Julia循环作用域问题:如何修改DataFrame值并保留到下一轮迭代?

问题:DataFrame迭代存储后所有元素均为最后一次结果

运行以下代码时,发现out0中存储的所有params DataFrame内容完全一致,全是最后一次迭代生成的值。但如果去掉player_id列,改用直接覆盖整个params的方式(注释掉的那行代码),结果就符合预期。

using DataFrames

# Simulation
out0   = Vector[];
nsim   = Int(1e1);

## Initialize player parameters to random integers between 1 and 100
params = rand(1:100, (5,4));
params = DataFrame(params, :auto);
params.player_id = 1:nrow(params);
params = params[!, [5; 1:4]];

for n in 1:nsim

    # Aggregate current simulation results
    df_vector = DataFrame[];
    push!(df_vector, params);

    # Add current results to final
    push!(out0, df_vector);
    
    # Update parameters
    params[!, 2:5] = max.(min.(params[!, 2:5] .+ rand(-2:2, 5, 4), 100), 0);
    # params = max.(min.(params .+ rand(-2:2, 5, 4), 100), 0);

end

原因分析

Julia里的DataFrame是引用类型,当你把params推入数组时,并没有复制一份新的DataFrame,只是存了指向原对象的引用。后续修改params的列数据时,所有存在数组里的引用都会指向这个被修改后的对象,所以最后看到的全是最后一次的结果。

而直接覆盖params(params = ...)时,是创建了一个全新的DataFrame对象,让params指向它。之前存在数组里的引用还是指向旧的对象,不会被后续修改影响,所以结果正常。

解决方案

每次存储前,先复制一份params的副本再推入数组,用copy()函数即可:

for n in 1:nsim

    # Aggregate current simulation results
    df_vector = DataFrame[];
    push!(df_vector, copy(params));  # 新增copy()创建副本

    # Add current results to final
    push!(out0, df_vector);
    
    # Update parameters
    params[!, 2:5] = max.(min.(params[!, 2:5] .+ rand(-2:2, 5, 4), 100), 0);

end

如果你的DataFrame包含嵌套的复杂结构,可以用deepcopy()替代copy(),但对于这个场景,copy()已经足够。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:24:54