El sábado, 4 de junio de 2016, 18:18:00 (UTC-4), Christopher Fisher escribió: > > Ok. I didn't anticipate this would be a drawn out process. I just Ford's > suggestion fixed the issue of changing values but recreated the problem of > accessing an individual's information like so: population[2] . > population[:,2] did not work either. I tried other changes to the syntax > but to no avail. It fails at the last line. Any ideas would be > appreciated. > > 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) > > > function Base.getindex(pop::Population, field::Symbol) > [getfield(x, field) for x in pop.individuals] > end > > setindex!(p::Population, value, field::Symbol, index...) = > p.individuals[index...].(field) = value > getindex(p::Population, field::Symbol, index...) = > p.individuals[index...].(field) > > Base.show(io::IO, p::Person) = print(io, "Person(infected=", p.infected, > ", vaccinated=", p.vaccinated, ", dead=", p.dead, ", history=", p.history) > > > population = Population() > push!(population, Person(true, false, true, [3,4,5])) > push!(population, Person(false, true, false, Int64[3,4,5])) > > #Show that it works > population[:infected] > population[:infected,1] > population[2] >
The syntax `population[x]` calls `getindex(population, x)`. You are using two different *types* of object x here: integers and symbols. If you really want to do this, you would thus need to define both getindex(p::Population, n::Integer) to return the nth individual, and getindex(p::Population, s::Symbol) to return the list of those with status s. However, this does not seem like a very good idea to me. What it sounds like you want to do is something like "find the first healthy individual and infect it". For this, you are better off writing a function called something like infect!(p::Population) which will choose an individual to infect. If you are planning to make this into an individual-based simulator, then you probably want to go back to just thinking of a vector of individuals, and maintain separately a list of those which are currently infected for example. Even though this will be extra book-keeping when an individual becomes infected or stops being infected, it will almost certainly be much faster. I suggest you try fleshing out your model a bit just thinking of functions that operate on the population as I have suggested. > > LoadError: MethodError: `size` has no method matching size(::Population) > Closest candidates are: > size(::Any, !Matched::Integer, !Matched::Integer, !Matched::Integer...) > while loading In[1], in expression starting on line 36 > > in getindex at abstractarray.jl:488 > > > > On Saturday, June 4, 2016 at 3:11:18 PM UTC-4, Ford O. wrote: >> >> I would like to discourage you from passing symbols as an array index but >> I guess you gonna do it anyway... >> >> >> So if you really want it, here it is: >> setindex!(p::Population, value, field::Symbol, index...) = p.individuals[ >> index...].(field) = value >> getindex(p::Population, field::Symbol, index...) = p.individuals[index >> ...].(field) >> >> Usage >> population[:infected, 1] >> population[:infected, 1] = false >> >> >> >> >> On Saturday, June 4, 2016 at 2:19:02 PM UTC+2, 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 >>> >>> Any help would be greatly appreciated. >>> >>