# How to save results for each outcome?

**URL:** <https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914>\
**Category:** Data\
**Created:** [February 24, 2021, 6:51am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914 "2021-02-24T06:51:56Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![younghan-lee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/younghan-lee/32/19224_2.png) [@younghan-lee](https://discourse.julialang.org/u/younghan-lee)\
**Post date:** [February 24, 2021, 6:51am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/1 "2021-02-24T06:51:56Z")

</div>

I am trying to save results for each outcome.  
For example,

```julia
list = [:A, :B]
for i in 1:length(list)
    result$i = lm((@eval @formula($i ~ x1 + x2)), data)
end

```

So that I can save the results for each outcome like result1, result2, … ,  
then export each result to csv file.  
Any ideas? Thank you 🙂

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [February 24, 2021, 7:36am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/2 "2021-02-24T07:36:42Z")

</div>

In Julia, we don’t have the concept of just indexing into a data structure at an index, and both data structure and index location are created if they don’t exist. That’s what you’re doing in your example, which is something like R I think?

You can either make an empty vector first, and then `push!` into it:

```julia
v = []
for i in 1:10
    push!(v, rand())
end

```

Above I used an untyped vector, `Vector{Any}`. That’s usually not good for performance, if your loop has a lot of runs. Then in this example it would be better to explicitly make an empty vector of floats.

```julia
v = Float64[]
for i in 1:10
    push!(v, rand())
end

```

But for this you need to know the element type you’ll get, which is sometimes not easy. For example I don’t know what the resulting type of your `lm` call would be. So my preferred solution is usually `map`, which goes over the elements of one or many iterables and automatically stores the result of a function called with the elements:

With your example:

```julia
list = [:A, :B]
result = map(1:length(list)) do i
    lm((@eval @formula($i ~ x1 + x2)), data)
end

```

The `do i` means we’re passing a function to map as the first argument, before `1:length(list)`. This function will be called for every element in `1:length(list)` and the current number will be the argument named `i` inside that function. It takes a moment to wrap your head around if you haven’t seen it, but it’s a really convenient syntax used widely in Julia wherever you want to pass a function first.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [February 24, 2021, 7:57am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/3 "2021-02-24T07:57:19Z")

</div>

I see you’re still using `@eval` to construct multiple regressions rather than terms… 😉

I think the main issue that you will have to deal with is how to turn your regression result into a tabular format, given that you want to write out the results to csv. I assume at a minimum you’d want your table to have (1) dependent variable and (2) estimated coefficients on your covariates. In that case you can do:

```julia
julia> using DataFrames

julia> list = [:A, :B];

julia> results = DataFrame("y" => list, (["x1", "x2"] .=> [Vector{Float64}(undef, length(list)) for _ ∈ 1:2])...)
2×3 DataFrame
 Row │ y x1 x2           
     │ Symbol Float64 Float64      
─────┼────────────────────────────────────
   1 │ A 1.53e-322 5.77183e-312
   2 │ B 6.95011e-310 0.0

```

You can then go through and fill your dataframe in a loop (this is pseudocode but should be more or less correct):

```julia
julia> for depvar ∈ list
           ols_result = lm(term(depvar) ~ term(:x1) + term(:x2), data)
           results[results.y .== devpar, :x1] = coef(ols_result)[1]
           results[results.y .== depvar, :x2] = coef(ols_result)[2]
       end

```

---

<div class="post-metadata">

**Author:** ![younghan-lee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/younghan-lee/32/19224_2.png) [@younghan-lee](https://discourse.julialang.org/u/younghan-lee)\
**Post date:** [February 24, 2021, 8:19am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/4 "2021-02-24T08:19:20Z")

</div>

@nilshg  
Wow this is very helpful. Thank you!  
I won’t use `@eval` anymore 😅  
I just have a quick question.  
When I run this part,

```julia
results = DataFrame( ...

```

I get an error saying no method matching DataFrame.  
Also, could you explain what the underscore means here? `for _ in 1:2`  
Thank you!

---

<div class="post-metadata">

**Author:** ![younghan-lee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/younghan-lee/32/19224_2.png) [@younghan-lee](https://discourse.julialang.org/u/younghan-lee)\
**Post date:** [February 24, 2021, 8:22am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/5 "2021-02-24T08:22:00Z")

</div>

Thanks for your kind explanation!  
For the my example part,  
Should I replace `$i` with `list[i]`?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [February 24, 2021, 8:25am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/6 "2021-02-24T08:25:47Z")

</div>

Ah I see, you wanted the symbols from `list` there. In that case, instead of interpolating `i`, you would interpolate `list[i]`, therefore the expression must be `$(list[i])` instead of `$i`. But you can have it even easier if you map over the symbols directly.

```julia
list = [:A, :B]
result = map(list) do sym
    lm((@eval @formula($sym ~ x1 + x2)), data)
end

```

---

<div class="post-metadata">

**Author:** ![younghan-lee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/younghan-lee/32/19224_2.png) [@younghan-lee](https://discourse.julialang.org/u/younghan-lee)\
**Post date:** [February 24, 2021, 8:29am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/7 "2021-02-24T08:29:04Z")

</div>

Thank you very much! 😄

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [February 24, 2021, 8:31am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/8 "2021-02-24T08:31:09Z")

</div>

Sure - my example above was incomplete, as you need `using DataFrames`. If you don’t want to use DataFrames, you could also construct something similar based on `NamedTuple`s, which can also be written to CSV.

I also realise I missed out the all important `CSV.write("results.csv", results)` as the final step after the loop.

Finally, on the `_` that’s just a placeholder for the variable that holds the value of the current iteration (here, either 1 or 2). People tend to use `_` to signify that the value is actually not used, i.e. you could use any valid identifier here and it wouldn’t change the output of the list comprehension (as we’re creating a `Vector{Float}(undef, length(list))` in every iteration step).

---

<div class="post-metadata">

**Author:** ![younghan-lee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/younghan-lee/32/19224_2.png) [@younghan-lee](https://discourse.julialang.org/u/younghan-lee)\
**Post date:** [February 24, 2021, 8:47am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/9 "2021-02-24T08:47:13Z")

</div>

Thank you for your clarification!  
The first part of your codes works perfectly now.  
The second part,

```julia
for depvar ∈ list
    ols_result = lm(term(depvar) ~ term(:x1) + term(:x2), data)
    results[results.y .== depvar, :x1] = coef(ols_result)[1]
    results[results.y .== depvar, :x2] = coef(ols_result)[2]
end

```

I get this error.

> ERROR: MethodError: no method matching setindex!(::DataFrame, ::Float64, ::BitArray{1}, ::Symbol)

What could be the problem?  
Thank you!

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [February 24, 2021, 11:11am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/10 "2021-02-24T11:11:06Z")

</div>

Sorry my fault for writing pseudocode - the DataFrame indexing in the loop returns a one-element array on the left hand side, so assignment needs to be broadcasted.

Here’s a full MWE (note the `.=` in the loop):

```julia
julia> using CSV, DataFrames, GLM

julia> data = DataFrame(x1 = rand(500), x2 = rand(500));

julia> data[!, :A] = 5 .+ 0.5*data.x1 - 1.5*data.x2 .+ randn.();

julia> data[!, :B] = 1 .+ 2.5*data.x1 + 3.5*data.x2 .+ randn.();

julia> list = [:A, :B];

julia> results = DataFrame("y" => list, (["x1", "x2"] .=> [Vector{Float64}(undef, length(list)) for _ ∈ 1:2])...);

julia> for depvar ∈ list
           ols_result = lm(term(depvar) ~ term(:x1) + term(:x2), data)
           results[results.y .== depvar, :x1] .= coef(ols_result)[1]
           results[results.y .== depvar, :x2] .= coef(ols_result)[2]
       end

julia> results
2×3 DataFrame
 Row │ y x1 x2       
     │ Symbol Float64 Float64  
─────┼────────────────────────────
   1 │ A 5.17577 0.495342
   2 │ B 0.975703 2.6233

```

---

<div class="post-metadata">

**Author:** ![younghan-lee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/younghan-lee/32/19224_2.png) [@younghan-lee](https://discourse.julialang.org/u/younghan-lee)\
**Post date:** [February 24, 2021, 11:43am UTC](https://discourse.julialang.org/t/how-to-save-results-for-each-outcome/55914/11 "2021-02-24T11:43:34Z")

</div>

Oh! I just needed a dot (`.`) before the equal sign (`=`). Now it works!  
Thank you so much for your time and explanation.  
I learned a lot ! 😄
