在 Julia 中的 for 循环中操作多个变量

Manipulating several variables within a for loop in Julia

我是 Julia 的新手。我想编写代码,对于几个向量中的每一个,输出一个新向量,其名称取决于输入向量的名称。

例如,下面的代码有效

a = ones(10) 
b = ones(10) 
for var in [a, b] 
  global log_var = log.(var)
end 

除了我希望生成的向量被命名为 log_alog_b(而不是让循环覆盖 log_var)。我原以为这会很简单,但在阅读了一些关于 Julia 当地人的教程后,我仍然迷路了!有没有简单的方法来解决这个问题?

如果这个问题不清楚,我将描述如何在我更熟悉的 Stata 中执行此操作:

clear 
set obs 10 
gen a = 1 
gen b = 1 
foreach var in a b {
gen log_`var' = log(`var')
}

谢谢!

您可能真的不想那样做。但是,如果必须的话,您可以使用 metaprogramming 轻松完成。例如在这种情况下:

macro logify(variable)
   quote
       $(esc(Symbol("log_$variable"))) = log.($variable)
   end
end

然后

julia> b = rand(5)
5-element Vector{Float64}:
 0.29129581739244315
 0.21098023915449915
 0.8736387630142392
 0.34378216482772417
 0.621583372934101

julia> @logify b;

julia> log_b
5-element Vector{Float64}:
 -1.2334159735391819
 -1.555990803188027
 -0.13508830339365252
 -1.0677470639708686
 -0.4754852291054692

一般来说,只要您需要依赖变量的名称而不是其内容,就需要元编程。

但是,再次强调,这感觉不是个好主意。

与其定义新的 top-level 变量,不如考虑使用某种数据结构,例如 DictNamedTupleDataFrame,甚至只是一个多维 Array。例如,使用 NamedTuples:

julia> data = (a = rand(5), b = rand(5));

julia> typeof(data)
NamedTuple{(:a, :b), Tuple{Vector{Float64}, Vector{Float64}}}

julia> data.a
5-element Vector{Float64}:
 0.7146929585896256
 0.5248314042991269
 0.040560190890127856
 0.9714549101298824
 0.9477790450084252

julia> data.b
5-element Vector{Float64}:
 0.6856764745285641
 0.3066093923258396
 0.5655243277481422
 0.13478854894985115
 0.8495720250298817

julia> logdata = NamedTuple{keys(data)}(log.(data[x]) for x in keys(data));

julia> logdata.a
5-element Vector{Float64}:
 -0.335902257064951
 -0.6446782026336225
 -3.204968213346185
 -0.02896042387181646
 -0.05363387877891503

julia> logdata.b
5-element Vector{Float64}:
 -0.3773493739743169
 -1.182180679204628
 -0.5700019644606769
 -2.0040480325554944
 -0.1630225562612911

如果您正在寻找类似于您在 stata 中所做的事情,您可以使用 DataFrames.jl

julia> using DataFrames
julia> df = DataFrame(a=ones(10), b=ones(10))
julia> for col in ["a", "b"]
           df[:, "log_"*col] = log.(df[:, col])
       end
julia> df

不真正推荐这种用法,但一个快速而肮脏的变体是

for var in [:a, :b] 
     @eval global $(Symbol("log_", var)) = log.($var)
end