Pre-Allocate Array Custom Struct with Zeroed Values

I am trying to figure out how to pre-allocate an array with a custom struct with zeroed values. I figured out how to allocate using undef, but I am uncertain how I can do that while setting the values other than a loop. It feels like I am missing something.

Method that works

using DataFrames, Dates

struct MyData
    rev::Float64
    qty::Int64
    MyData() = new(0,0)
end

arr =[]
for i in 1:10
    push!(arr,MyData())
end

time_series = DataFrame()
for date in Date(2019,1):Dates.Month(1):Date(2020,12)
    time_series[Symbol(date)] = arr
end

ts
10Ɨ24 DataFrame. Omitted printing of 17 columns
ā”‚ Row   ā”‚ 2019-01-01     ā”‚ 2019-02-01     ā”‚ 2019-03-01     ā”‚ 2019-04-01     ā”‚ 2019-05-01     ā”‚ 2019-06-01     ā”‚ 2019-07-01     ā”‚
ā”‚       ā”‚ Any            ā”‚ Any            ā”‚ Any            ā”‚ Any            ā”‚ Any            ā”‚ Any            ā”‚ Any            ā”‚     
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤     
ā”‚ 1     ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚     
ā”‚ 2     ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚     
ā”‚ 3     ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚
ā”‚ 4     ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚     
ā”‚ 5     ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚     
ā”‚ 6     ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚     
ā”‚ 7     ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚ MyData(0.0, 0) ā”‚     

Thing I sort of wish I could do

for date in Date(2019,1):Dates.Month(1):Date(2020,12)
    time_series[Symbol(date)] = Array{MyData}(ZeroSomehow,100)
end

Am I missing a more Julian way of getting this done? I checked the source for answers, but I was unable to figure out much from UndefInitializer. I am not good at digging through it yet.

You mean this part?

Coud be done with:

arr = [ MyData() for i in 1:10 ]

for example.

Edit: Yet, you would not be able to change the values, because they are immutable. (probably this is what you are asking?)

The options are: 1) use a mutabe struct instead or 2) whenever you want to change the content of arr, you have to initialize the complete struct in each position. I would do:

struct MyData
  rev :: Float64
  qty :: Int64
end
MyData() = MyData(0,0)
arr = [ MyData() for i in 1:10 ]
arr[5] = MyData(1,1) # for example

Iā€™m not sure what you are trying to do, but

Vector{MyData}(undef, 10)

should work to preallocate with undef. If you need zeros, then you have to fill it, e.g., with

fill(MyData(), 10)
1 Like

Yup, I was going for mutable. I am trying to vcat some DataFrames together, so I know the size of the dataframe before adding data to it. Not sure if it makes sense to try and allocated it before hand or not.

I think I was looking for fill and somehow kept missing how to use it. I think that is what I am looking for. Now that i am looking at it I feel that I am focusing too much on allocating memory early. I am just not sure how to find a middle ground between undef and a union with nothing.

I think it is generally better to keep it immutable and redefine the structures in the desired positions (the vector as whole is mutable).

1 Like

I ended up just making some arrays to hold the values then cast them into a DataFrame once I was done parsing. I keep getting caught up in types and allocating. Probably my c++ background showing. Just seemed like a thing I should have been able to do. turns out I made some sort of recursive pointer doing it the way I showed and everything was just a reference to arr. Cost of abstraction I suppose.

Thank you all so much