You can define a `Population` type and overload `getindex` for it to do 
what you want, something like:

type Person
    infected::Bool
    vaccinated::Bool
    dead::Bool
    history::Vector{Int}
end

type Population <: AbstractArray
    individuals::Vector{Person}
end


Population() = Population(Person[])
Base.push!(p::Population, x::Person) = push!(p.individuals, x)
length(p::Population) = length(p.individuals)
size(p::Population) = size(p.individuals)

function Base.getindex(pop::Population, field::Symbol)
    [getfield(x, field) for x in pop.individuals]
end

population = Population()
push!(population, Person(true, false, true, [3,4,5]))
push!(population, Person(false, true, false, Int64[3,4,5]))

population[:infected]


Note that this is not very efficient; I believe the following package may 
be an alternative / better solution:

 https://github.com/simonster/StructsOfArrays.jl



El sábado, 4 de junio de 2016, 11:13:21 (UTC-4), Christopher Fisher 
escribió:
>
> Thanks for your suggestions Steven. You are correct. I could many of those 
> fields as Boolean and maybe there is a reason to prefer that rather than 
> using 1 and 0s. 
>
> Initially, I also tried to push the individuals into an empty array as you 
> suggested. This worked well, except I was not able to query across 
> individuals:
>
> type Person
>     infected::Int64
>     vaccinated::Int64
>     dead::Int64
>    history::Array{Int64,1}
> end
> population = Person[]   # create an empty population
> push!(population, Person(0, 2, 0, Int64[3,4,5]))   # add a person to the 
> population
> push!(population, Person(0, 2, 0, Int64[3,4,5]))
> population.infected
>
> LoadError: type Array has no field infected
> while loading In[16], in expression starting on line 10
>
>
>
> What I was hoping is that it would list the infection status for all 
> members of the population. Is there any way to do that?
>
>
> On Saturday, June 4, 2016 at 10:47:55 AM UTC-4, Steven G. Johnson wrote:
>>
>>
>>
>> On Saturday, June 4, 2016 at 8:19:02 AM UTC-4, Christopher Fisher wrote:
>>>
>>> I was wondering if someone would be willing to help me with creating 
>>> user-defined types. I've been using Julia for about two years now but I am 
>>> new to the idea of creating custom types. I'm trying to create a population 
>>> of agents/individuals in a simple epidemiological simulation. I would like 
>>> the population of individuals to be structured as a  2 dimensional array 
>>> with rows as individuals and columns as properties. This would be somewhat 
>>> similar to a DataFrame, but potentially more flexible. I want to be able to 
>>> index an individual like so: population[1]. This woud list all of the 
>>> information for individual 1.  I would also like to be able to look at an 
>>> attribute across individuals: population.infected or population[:infected]. 
>>> At the same time, I would like to have to flexibility of using an array to 
>>> keep track of individuals: typeof(population.history[1]) is Array{Int64,1}. 
>>> Based on existing documentation and examples, I have only been able to 
>>> create individuals but cannot figure out how to create a population as 
>>> described above:
>>>
>>> type Person
>>>     infected::Int64
>>>     vaccinated::Int64
>>>     dead::Int64
>>>    history::Array{Int64,1}
>>> end
>>>
>>
>> It sounds like you just want an array of your Person type.
>>
>> e.g.
>>
>> population = Person[]   # create an empty population
>> push!(population, Person(0, 2, 0, Int64[3,4,5]))   # add a person to the 
>> population
>> population[1].dead # access the "dead" field of the first person in the 
>> population
>> population[1].history[3]  # access history[3] from person 1
>>
>> Of course, you can make working with the Person type a lot nicer by 
>> defining more methods.   e.g. you probably want to have a "show" method to 
>> pretty-print a person, for example:
>>
>> Base.show(io::IO, p::Person) = print(io, "Person(infected=", p.infected, 
>> ", vaccinated=", p.vaccinated, ", dead=", p.dead, ", history=", p.history)
>>
>> When designing your types, you also want to think carefully about your 
>> fields.   e.g. aren't infected, dead, etc. really Boolean fields?  If you 
>> can encode "history" into a fixed-width field (e.g. a single 64-bit 
>> integer), it will be much more efficient.  And arrays of persons will be 
>> more efficient if you can make the person immutable --- you only need a 
>> (mutable) type if you need to have multiple references to the same 
>> individual, where modifying one reference's fields will change the data 
>> seen from all the references.
>>
>

Reply via email to