# Dynamically generate DataFrame in function with number of columns determined by length of array arguments

**URL:** <https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446>\
**Category:** General Usage\
**Tags:** question\
**Created:** [June 23, 2021, 2:34pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446 "2021-06-23T14:34:13Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 2:34pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/1 "2021-06-23T14:34:13Z")

</div>

```julia-auto
"""
I am trying to generate a function that creates a DataFrame dynamically with number of columns determined by length of array arguments (n) to the function. 
But I failed to generate the DataFrame dynamically because I don't understand how to use a `for loop` to generate DataFrame columns.

Noticed that the dataframe is defined in lines 19 through 30 and lines 25 through 28 are the old code that did not attempt dynamic generation of the DataFrame columns. 
The attempted for loop in lines 21 through 23 does not work and something needs to replace it.
"""

```

{  
function testf(x, y, z) # inputs are arrays measured over time periods of a year; by definition, x - y = z, or y = x - z  
n = length(x)  
td = today()  
byr = year(td) - t # calcs the current base year

# 

```
if sum(y) == 0 && mode(y) == 0 && length(z) == n # inner if for case where y is unkown and will be derived from x and z
  	y = y .+ (x .- z)

```

# 

```
	zx = zeros(n); # placeholder z to x ratio array 
	zy = zeros(n); # placeholder z to y ratio array
	for i in 1:n
  		zx[i] = z[i]/x[i]; # filling the zx ratio array through nth element
  		zy[i] = z[i]/y[i]; # filling the zy ratio array through nth element
	end # for i loop

```

# 

```
	ave_zx = mean(zx); ave_zy = mean(zy); 
	ave_zx_rnd = round(ave_zx,digits=6); ave_zy_rnd = round(ave_zy,digits=6);

```

# 

```
	df1 = DataFrame([:item => ["x", "y", "z", repeat("-", 12), "z/x", "z/y", "Ave(z)/Ave(x)", "Ave(z)/Ave(y)"], # begin dynamic DF generation based on n = length of data arrays
#
		for j in 1:n
			Symbol(byr-(j-1)) => [x[j], y[j], z[j], repeat("-", 12), round(zx[j],digits=6), round(zy[j],digits=6), "n/a", "n/a"],
		end # for loop
#
# Symbol(byr-0) => [x[1], y[1], z[1], repeat("-", 12), round(zx1,digits=6), round(zy1,digits=6), "n/a", "n/a"], # this is previous code used to fill df1 before for loop idea 
# Symbol(byr-1) => [x[2], y[2], z[2], repeat("-", 12), round(zx2,digits=6), round(zy2,digits=6), "n/a", "n/a"], # this is previous code used to fill df1 before for loop idea 
# Symbol(byr-2) => [x[3], y[3], z[3], repeat("-", 12), round(zx3,digits=6), round(zy3,digits=6), "n/a", "n/a"], # this is previous code used to fill df1 before for loop idea
# Symbol("Ave($(byr-(2))-$(byr))") => [ave_x_rnd, ave_y_rnd, ave_z_rnd, repeat("-", 12), ave_zx_rnd, ave_zy_rnd, ave_z_to_ave_x_rnd, ave_z_to_ave_y_rnd] # this is previous code used to fill df1 before for loop idea
	Symbol("Ave($(byr-(j-1))-$(byr))") => [ave_x_rnd, ave_y_rnd, ave_z_rnd, repeat("-", 12), ave_zx_rnd, ave_zy_rnd, ave_z_to_ave_x_rnd, ave_z_to_ave_y_rnd]
	]) # end dynamic DF generation based on n = length of data arrays

```

# 

```
println()
show(df1) # display the dynamic DataFrame generated by the for loop
println()

```

# 

```
else
	println("The function testf() has errors and cannot execute.")	
end # end if sum(y) == 0...

```

end # end function testf()  
}

```julia-auto

"""
I'm trying to generate output like this for the case of n=3.
"""

```

│ Row │ item │ 2020 │ 2019 │ 2018 │ Ave(2018-2020) │  
│ │ Any │ Any │ Any │ Any │ Any │  
├─────┼───────────────┼──────────────┼──────────────┼──────────────┼────────────────┤  
│ 1 │ x │ 31323718 │ 14342460 │ 10353288 │ 1.86732e7 │  
│ 2 │ y │ 30609098 │ 14188281 │ 10066719 │ 1.8288e7 │  
│ 3 │ z │ 714620.0 │ 154179.0 │ 286569.0 │ 3.85123e5 │  
│ 4 │ ------------ │ ------------ │ ------------ │ ------------ │ ------------ │  
│ 5 │ z/x │ 0.022814 │ 0.01075 │ 0.027679 │ 0.020414 │  
│ 6 │ z/y │ 0.023347 │ 0.010867 │ 0.028467 │ 0.020893 │  
│ 7 │ Ave(z)/Ave(x) │ n/a │ n/a │ n/a │ 0.020624 │  
│ 8 │ Ave(z)/Ave(y) │ n/a │ n/a │ n/a │ 0.021059 │

```julia-auto
![image|690x206](upload://hZVoNOa4yWWfAUe4DcUkkPcZHRk.png)
```

---

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 2:36pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/2 "2021-06-23T14:36:56Z")

</div>

![image](https://global.discourse-cdn.com/julialang/original/3X/f/6/f655a137b2c7be965d938c0dd36eb98e6a664a08.png)

---

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 2:38pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/3 "2021-06-23T14:38:17Z")

</div>

sorry, formatting is not ideal here:

function testf(x, y, z) # inputs are arrays measured over time periods of a year; by definition, x - y = z, or y = x - z  
n = length(x)  
td = today()  
byr = year(td) - t # calcs the current base year

# 

```
if sum(y) == 0 && mode(y) == 0 && length(z) == n # inner if for case where y is unkown and will be derived from x and z
  	y = y .+ (x .- z)

```

# 

```
	zx = zeros(n); # placeholder z to x ratio array 
	zy = zeros(n); # placeholder z to y ratio array
	for i in 1:n
  		zx[i] = z[i]/x[i]; # filling the zx ratio array through nth element
  		zy[i] = z[i]/y[i]; # filling the zy ratio array through nth element
	end # for i loop

```

# 

```
	ave_zx = mean(zx); ave_zy = mean(zy); 
	ave_zx_rnd = round(ave_zx,digits=6); ave_zy_rnd = round(ave_zy,digits=6);

```

# 

```
	df1 = DataFrame([:item => ["x", "y", "z", repeat("-", 12), "z/x", "z/y", "Ave(z)/Ave(x)", "Ave(z)/Ave(y)"], # begin dynamic DF generation based on n = length of data arrays
#
		for j in 1:n
			Symbol(byr-(j-1)) => [x[j], y[j], z[j], repeat("-", 12), round(zx[j],digits=6), round(zy[j],digits=6), "n/a", "n/a"],
		end # for loop
#
# Symbol(byr-0) => [x[1], y[1], z[1], repeat("-", 12), round(zx1,digits=6), round(zy1,digits=6), "n/a", "n/a"], # this is previous code used to fill df1 before for loop idea 
# Symbol(byr-1) => [x[2], y[2], z[2], repeat("-", 12), round(zx2,digits=6), round(zy2,digits=6), "n/a", "n/a"], # this is previous code used to fill df1 before for loop idea 
# Symbol(byr-2) => [x[3], y[3], z[3], repeat("-", 12), round(zx3,digits=6), round(zy3,digits=6), "n/a", "n/a"], # this is previous code used to fill df1 before for loop idea
# Symbol("Ave($(byr-(2))-$(byr))") => [ave_x_rnd, ave_y_rnd, ave_z_rnd, repeat("-", 12), ave_zx_rnd, ave_zy_rnd, ave_z_to_ave_x_rnd, ave_z_to_ave_y_rnd] # this is previous code used to fill df1 before for loop idea
	Symbol("Ave($(byr-(j-1))-$(byr))") => [ave_x_rnd, ave_y_rnd, ave_z_rnd, repeat("-", 12), ave_zx_rnd, ave_zy_rnd, ave_z_to_ave_x_rnd, ave_z_to_ave_y_rnd]
	]) # end dynamic DF generation based on n = length of data arrays

```

# 

```
println()
show(df1) # display the dynamic DataFrame generated by the for loop
println()

```

# 

```
else
	println("The function testf() has errors and cannot execute.")	
end # end if sum(y) == 0...

```

end # end function testf()

---

<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:** [June 23, 2021, 2:42pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/4 "2021-06-23T14:42:10Z")

</div>

Lots of code there, but you can just do

```julia
df = DataFrame()

for x in my_suff
    df[!, x] = ...
end

```

---

<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:** [June 23, 2021, 2:44pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/5 "2021-06-23T14:44:15Z")

</div>

This is all pretty convoluted but if I read correctly it seems to boil down to the fact that you are putting a loop inside the DataFrames constructor, which doesn’t work.

The normal way is to do what Peter says above. Alternatively, you could replace your loop with a comprehension, so instead of

```julia
DataFrame(x => some_vector, 
          for i in 1:10
              Symbol(col_$i) => f(i)
          end)

```

you could have

```julia
DataFrame(x => some_vector, [Symbol(col_$i) => f(i) for i in 1:10]...)

```

---

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 7:37pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/6 "2021-06-23T19:37:54Z")

</div>

## update as of 12pm PDT Wed 6/23/21

here is a fixed update based on recommendations received this morning, stripping away complexity to address the posting question:

using DataFrames

julia\> x = [1\_000\_000, 1\_200\_000, 1\_500\_000]; y = [800\_000, 900\_000, 1\_100\_000]; z = [200\_000, 300\_000, 400\_000];

julia\> n = length(x)  
3

julia\> df = DataFrame([Symbol(“col\_$j”) =\> [x[j], y[j], z[j]] for j in 1:n]…)  
3×3 DataFrame  
│ Row │ col\_1 │ col\_2 │ col\_3 │  
│ │ Int64 │ Int64 │ Int64 │  
├─────┼─────────┼─────────┼─────────┤  
│ 1 │ 1000000 │ 1200000 │ 1500000 │  
│ 2 │ 800000 │ 900000 │ 1100000 │  
│ 3 │ 200000 │ 300000 │ 400000 │

here is a more detailed version of the fix applied to my original posting question:

using Statistics, StatsBase, DataFrames

function testf(x, y, z; t=0) # inputs are arrays measured over time periods of a year; by definition, x - y = z, or y = x - z  
n = length(x)  
td = today()  
yr = year(td) - t # calcs the current base year

# 

```
if sum(y) == 0 && mode(y) == 0 && length(z) == n # inner if for case where y is unkown and will be derived from x and z
  	y = y .+ (x .- z)

```

# 

```
	zx = zeros(n); # placeholder z to x ratio array 
	zy = zeros(n); # placeholder z to y ratio array
	for i in 1:n
  		zx[i] = z[i]/x[i]; # filling the zx ratio array through nth element
  		zy[i] = z[i]/y[i]; # filling the zy ratio array through nth element
	end # for i loop

```

# 

```
	ave_zx = mean(zx); ave_zy = mean(zy); 
	ave_zx_rnd = round(ave_zx,digits=6); ave_zy_rnd = round(ave_zy,digits=6);

```

# 

df1 = DataFrame(  
:item =\> [“x”, “y”, “z”, repeat(“-”, 12), “z/x”, “z/y”],  
[Symbol(“$(yr-(j-1))”) =\> [x[j], y[j], z[j], repeat(“-”, 12), round(zx[j],digits=6), round(zy[j],digits=6)] for j in 1:n]…)

# 

```
println()
show(df1) # display the dynamic DataFrame generated by the splat ...
println()

```

# 

```
else
	println("The function testf() has errors and cannot execute.")	
end # end if sum(y) == 0...

```

end # end function testf()

julia\> testf([1\_000\_000, 1\_200\_000, 1\_500\_000, 1\_600\_000], zeros(4), [200\_000, 300\_000, 400\_000, 500\_000])

6×5 DataFrame  
│ Row │ item │ 2021 │ 2020 │ 2019 │ 2018 │  
│ │ String │ Any │ Any │ Any │ Any │  
├─────┼──────────────┼──────────────┼──────────────┼──────────────┼──────────────┤  
│ 1 │ x │ 1000000 │ 1200000 │ 1500000 │ 1600000 │  
│ 2 │ y │ 800000.0 │ 900000.0 │ 1.1e6 │ 1.1e6 │  
│ 3 │ z │ 200000 │ 300000 │ 400000 │ 500000 │  
│ 4 │ ------------ │ ------------ │ ------------ │ ------------ │ ------------ │  
│ 5 │ z/x │ 0.2 │ 0.25 │ 0.266667 │ 0.3125 │  
│ 6 │ z/y │ 0.25 │ 0.333333 │ 0.363636 │ 0.454545 │

---

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 7:39pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/7 "2021-06-23T19:39:27Z")

</div>

![image](https://global.discourse-cdn.com/julialang/original/3X/9/8/980c4e05b52d80f7b76e0788e67f6a4a9df99ba1.png)

---

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 7:41pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/8 "2021-06-23T19:41:08Z")

</div>

![image](https://global.discourse-cdn.com/julialang/original/3X/0/7/0714faa1e50460e8876ce1587d7911d296478d66.png)

---

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 7:41pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/9 "2021-06-23T19:41:57Z")

</div>

![image](https://global.discourse-cdn.com/julialang/original/3X/5/e/5e4f09ef791c3f48c84234018cbbc1130d2eaaac.png)

---

<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:** [June 23, 2021, 8:04pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/10 "2021-06-23T20:04:57Z")

</div>

I’m confused. Did you attempt the solution I presented earlier in the thread? Did it nt fit your use-case for some reason?

Additionally, please make sure you are blocking your code correctly.

Your breaks `---` in the data frame are a bit unusual. See PrettyTables.jl for a better solution to break up your data frame into parts while printing.

---

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 8:13pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/11 "2021-06-23T20:13:33Z")

</div>

> [@dfa\_julia\_quant](#):
>
> df = DataFrame([Symbol(“col\_$j”) =\> [x[j], y[j], z[j]] for j in 1:n]…)

Yes, indirectly through nilshg’s comments.

The essential part I learned from both you and nilshg is:

df = DataFrame([Symbol(“col\_$j”) =\> [x[j], y[j], z[j]] for j in 1:n]…)

---

<div class="post-metadata">

**Author:** ![dfa\_julia\_quant](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dfa\_julia\_quant](https://discourse.julialang.org/u/dfa_julia_quant)\
**Post date:** [June 23, 2021, 8:20pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/12 "2021-06-23T20:20:06Z")

</div>

This is how it looks in my function that is context specific to my application (with PrettyTables.jl):

```julia
┌───────────────┬──────────────┬──────────────┬──────────────┬────────────────┐
│ item │ 2020 │ 2019 │ 2018 │ Ave(2018-2020) │
├───────────────┼──────────────┼──────────────┼──────────────┼────────────────┤
│ R │ 31,323,718 │ 14,342,460 │ 10,353,288 │ 18,673,155 │
│ C │ 30,609,098 │ 14,188,281 │ 10,066,719 │ 18,288,033 │
│ G │ 714,620 │ 154,179 │ 286,569 │ 385,123 │
│ ------------ │ ------------ │ ------------ │ ------------ │ ------------ │
│ G/R │ 0.022814 │ 0.01075 │ 0.027679 │ 0.020414 │
│ G/C │ 0.023347 │ 0.010867 │ 0.028467 │ 0.020893 │
│ Ave(G)/Ave(R) │ n/a │ n/a │ n/a │ 0.020624 │
│ Ave(G)/Ave(C) │ n/a │ n/a │ n/a │ 0.021059 │
└───────────────┴──────────────┴──────────────┴──────────────┴────────────────┘

```

---

<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:** [June 23, 2021, 8:53pm UTC](https://discourse.julialang.org/t/dynamically-generate-dataframe-in-function-with-number-of-columns-determined-by-length-of-array-arguments/63446/13 "2021-06-23T20:53:17Z")

</div>

What I mean to say is that having `---` as a _value_ in your DataFrame column is very awkward.

1. It means your column are of type `Vector{Any}` which is bad for performance
2. It means your vectors have an awkward string `"----"` in the middle.

PrettyTables allows you to have your data frame _not_ include the `"---"` but display it with horizontal lines for legibility.
