# Create variables in a loop

**URL:** <https://discourse.julialang.org/t/create-variables-in-a-loop/49549>\
**Category:** New to Julia\
**Tags:** data\
**Created:** [November 3, 2020, 6:56pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549 "2020-11-03T18:56:15Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Albert\_Zevelev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albert_zevelev/32/11844_2.png) [@Albert\_Zevelev](https://discourse.julialang.org/u/Albert_Zevelev)\
**Post date:** [November 3, 2020, 6:56pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/1 "2020-11-03T18:56:15Z")

</div>

Suppose I wanna create some routine econ variables:

```julia
using FredData;
const f = Fred("Personal api_key");  
#
d = get_data(f, "GDP"); y=d.df[:,4]
d = get_data(f, "PCEC"); c=d.df[:,4]
d = get_data(f, "GPDI"); i=d.df[:,4]
d = get_data(f, "GCE"); g=d.df[:,4]
d = get_data(f, "NETEXP"); nx=d.df[:,4]

```

Q: what is the best Julian way to automate this in a loop or something?

I had something in mind along the lines of:

```julia
vars = ["GDP", "PCEC", "GPDI", "GCE", "NETEXP"]
labs = [y, c, i, g, nx]
for (ii, dd) in enumerate(vars)
	d = get_data(f, dd) # get data, eg "GDP"
	labs[ii] = d.df[:,4] # create var, eg y="GDP"
    filter!(x -> ! isnan(x), labs[ii]) # remove NaN from var
end 

```

This clearly doesn’t work …

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [November 3, 2020, 7:18pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/2 "2020-11-03T19:18:52Z")

</div>

It’s better to use dictionaries in this case

```julia
dict = Dict{Symbol, Any}()
vars = Dict{String, Symbol}("GDP" => :y, 
                                            "PCEC" => :c,
                                            "GPDI" => :i,
                                            "GCE" => :g, 
                                            "NETEXP" => :nx)
for (k, v) in vars
   d = get_data(f, k)
   dict[v] = d.df[:4]
end

# example of using variable
dict[:nx] # some value

# Or even
dict[vars["NETEXP"]] # the same as dict[:nx]

```

If you know types in advance it’s better to use them instead of `Any`.

---

<div class="post-metadata">

**Author:** ![Albert\_Zevelev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albert_zevelev/32/11844_2.png) [@Albert\_Zevelev](https://discourse.julialang.org/u/Albert_Zevelev)\
**Post date:** [November 3, 2020, 7:29pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/3 "2020-11-03T19:29:51Z")

</div>

@Skoffer thank you, this is great!  
Right now the data is in `dict[:y]`.  
Is it possible to create the variable `y=d.df[:,4]` directly inside the loop?

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [November 3, 2020, 7:37pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/4 "2020-11-03T19:37:28Z")

</div>

I suppose it can be done with some macros magic, but it is not a recommended way of doing things.

---

<div class="post-metadata">

**Author:** ![Albert\_Zevelev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albert_zevelev/32/11844_2.png) [@Albert\_Zevelev](https://discourse.julialang.org/u/Albert_Zevelev)\
**Post date:** [November 3, 2020, 7:50pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/5 "2020-11-03T19:50:34Z")

</div>

> [@Skoffer](#):
>
> If you know types in advance it’s better to use them instead of `Any` .

is that mainly for speed?

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [November 3, 2020, 8:26pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/6 "2020-11-03T20:26:18Z")

</div>

Yes, for type stability and performance.

---

<div class="post-metadata">

**Author:** ![Albert\_Zevelev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albert_zevelev/32/11844_2.png) [@Albert\_Zevelev](https://discourse.julialang.org/u/Albert_Zevelev)\
**Post date:** [November 3, 2020, 9:18pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/7 "2020-11-03T21:18:02Z")

</div>

Does anyone here know how to generate (non-dictionary) variables in a loop? (my original question)

It’s very very easy in STATA where we do it all the time

```nohighlight
clear*
set obs 10
gen yr = _n
gen treated = 1*(yr >= 3)
* dummies for each year post treatment
forvalues y = 0(1)7 {
	gen treated_p`y' = 1*(yr == 3 + `y' )
}
* dummies for each year pre treatment
forvalues y = 1(1)2 {
	gen treated_m`y' = 1*(yr == 3 - `y' )
}

```

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [November 3, 2020, 9:30pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/8 "2020-11-03T21:30:14Z")

</div>

Remember that Stata doesn’t have the same constraints Julia. There is never any dispute about what the variable `x` represents: it’s always a column in the data set.

Of course, it easy to do this in DataFrames. Part of the switch to using Strings as column names is to make this kind of Stata workflow easier.

```julia
for y in string.(0:7)
    df[!, "treated_p" * y] = 1 .* df.yr .== 1 + df[!, y]
end

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [November 3, 2020, 9:31pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/9 "2020-11-03T21:31:28Z")

</div>

I think that, in this case, writing a macro may be your best option. Unless you are satisfied by some solution like:

```julia
function get_fourth_column(d) # unnecessary but simplifies
    return d.df[:, 4]
end
fields = ["GDP", "PCEC", "GPDI", "GCE", "NETEXP"]

y, c, i, g, nx = get_fourth_column.(get_data.((f,), fields))

```

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [November 3, 2020, 10:34pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/10 "2020-11-03T22:34:42Z")

</div>

Also, I take it that this is a feature you might be interested in seeing in seeing in DataFramesMeta? I prototyped this just now.

```julia
julia> df = DataFrame(a = [1, 1, 1, 2, 2, 2], b = [1, 2, 3, 100, 200, 300])
6×2 DataFrame
│ Row │ a │ b │
│ │ Int64 │ Int64 │
├─────┼───────┼───────┤
│ 1 │ 1 │ 1 │
│ 2 │ 1 │ 2 │
│ 3 │ 1 │ 3 │
│ 4 │ 2 │ 100 │
│ 5 │ 2 │ 200 │
│ 6 │ 2 │ 300 │

julia> @with df begin 
       for i in 1:10
           @gen cols("y" * string(i)) = :a .+ i 
       end
       nothing
       end

julia> df
6×12 DataFrame
│ Row │ a │ b │ y1 │ y2 │ y3 │ y4 │ y5 │ y6 │ y7 │ y8 │ y9 │ y10 │
│ │ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │
├─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤
│ 1 │ 1 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
│ 2 │ 1 │ 2 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
│ 3 │ 1 │ 3 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
│ 4 │ 2 │ 100 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ 12 │
│ 5 │ 2 │ 200 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ 12 │
│ 6 │ 2 │ 300 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ 12 │

```

EDIT: Although realistically I would probably rather have a more general solution so that it’s easier to construct many different arguments inside a `transform` call.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [November 3, 2020, 11:14pm UTC](https://discourse.julialang.org/t/create-variables-in-a-loop/49549/11 "2020-11-03T23:14:16Z")

</div>

Here’s something you can do on DataFramesMeta `master` right now

```julia
julia> @time transform(df, [DataFramesMeta.@col cols("y" * "$i") = :a .+ i for i in 1:10]...)

```

This is pretty good! can probably be tweaked a bit to make it cleaner.
