在 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_a
和 log_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 变量,不如考虑使用某种数据结构,例如 Dict
或 NamedTuple
或 DataFrame
,甚至只是一个多维 Array
。例如,使用 NamedTuple
s:
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
我是 Julia 的新手。我想编写代码,对于几个向量中的每一个,输出一个新向量,其名称取决于输入向量的名称。
例如,下面的代码有效
a = ones(10)
b = ones(10)
for var in [a, b]
global log_var = log.(var)
end
除了我希望生成的向量被命名为 log_a
和 log_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 变量,不如考虑使用某种数据结构,例如 Dict
或 NamedTuple
或 DataFrame
,甚至只是一个多维 Array
。例如,使用 NamedTuple
s:
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