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.
>>
>