Home > OS >  Manipulating several variables within a for loop in Julia
Manipulating several variables within a for loop in Julia

Time:01-30

I'm new to Julia. I want to write code which, for each of several vectors, outputs a new vector, the name of which depends on the name of the input vector.

For example, the following code works

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

except I want the resulting vectors to be named log_a and log_b (rather than have the loop overwrite log_var). I had thought this would be simple, but having read a few tutorials about locals in Julia, I'm still lost! Is there a simple way to go about this?

In case this question is unclear, I'll describe how I would do this in Stata, with which I'm more familiar:

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

Thank you!

CodePudding user response:

You really probably don't want to do that. But, if you had to, you could do it pretty easily with metaprogramming. In this case for example:

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

then

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

In general, any time you need to depend on the name of a variable rather than its contents, you're going to need metaprogramming.

However, to emphasize, again, this feels like a bad idea.

Rather than defining new top-level variables, you might consider instead using some sort of data structure like a Dict or a NamedTuple or a DataFrame, or even just a multidimensional Array. For example, with 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

CodePudding user response:

if you are looking for something similar to what you do in stata, you can use 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
  •  Tags:  
  • Related