Ejemplo n.º 1
0
    def birth(self):
        # construct fertility lookup for the current timestep, means a left join with zero missing values (male or too young/old)
        fert = pd.DataFrame({
            "age":
            self.fert.age,
            "gender":
            np.full(len(self.fert), False),
            "fertility_rate":
            self.fert[str(int(neworder.timeline.time()))].values
        })

        frates = pd.merge(self.pp, fert,
                          how='left').fillna(0.0)["fertility_rate"].values

        self.pp["__baby"] = neworder.hazard(frates * neworder.timestep)

        # clone mothers (hh id persists)
        newborns = self.pp[self.pp["__baby"] == True].copy()
        newborns.mother_id = newborns.id
        newborns.id = range(self.iditer, self.iditer + len(newborns))
        self.iditer = self.iditer + len(newborns)
        newborns.partner_id = UNSET
        newborns.dur_in_couple = UNSET
        newborns.civilstate = RelationshipStatus.SINGLE.value
        newborns.age = 0
        newborns.agegroup_civilstate = 0
        #newborns.workstate = 0
        newborns.gender = neworder.hazard(0.51, len(newborns))

        #neworder.log(newborns)
        self.pp = self.pp.append(newborns)
Ejemplo n.º 2
0
    def births(self, deltat):
        # First consider only females
        females = self.data[self.data.DC1117EW_C_SEX == 2].copy()

        # Now map the appropriate fertility rate to each female
        # might be a more efficient way of generating this array
        rates = females.join(
            self.fertility,
            on=["NewEthpop_ETH", "DC1117EW_C_SEX",
                "DC1117EW_C_AGE"])["Rate"].values
        # Then randomly determine if a birth occurred (neworder callback)
        h = neworder.hazard(rates * deltat)

        # The babies are a clone of the new mothers, with with changed PID, reset age and randomised gender (keeping location and ethnicity)
        newborns = females[h == 1].copy()
        newborns.PID = range(self.counter, self.counter + len(newborns))
        newborns.Age = neworder.ustream(
            len(newborns))  # born within the last 12 months
        newborns.DC1117EW_C_AGE = 1  # this is 0-1 in census category
        # NOTE: do not convert to pd.Series here to stay as this has its own index which conflicts with the main table
        newborns.DC1117EW_C_SEX = neworder.hazard(0.5, len(newborns)) + 1

        # Finally append newborns to main population and adjust counter
        self.data = self.data.append(newborns)
        self.counter = self.counter + len(newborns)
Ejemplo n.º 3
0
def test():
    t = test_.Test()

    # Exp.value = p +/- 1/sqrt(N)
    h = neworder.hazard(0.2, 10000)
    t.check(isinstance(h, np.ndarray))
    t.check(len(h) == 10000)
    t.check(abs(np.mean(h) - 0.2) < 0.01)

    hv = neworder.hazard(np.array([0.1, 0.2, 0.3, 0.4, 0.5]))
    t.check(isinstance(hv, np.ndarray))
    t.check(len(hv) == 5)

    # Exp.value = 1/p +/- 1/sqrt(N)
    s = neworder.stopping(0.1, 10000)
    t.check(isinstance(s, np.ndarray))
    t.check(len(s) == 10000)
    t.check(abs(np.mean(s) / 10 - 1.0) < 0.03)

    sv = neworder.stopping(np.array([0.1, 0.2, 0.3, 0.4, 0.5]))
    t.check(isinstance(sv, np.ndarray))
    t.check(len(sv) == 5)

    # Non-homogeneous Poisson process (time-dependent hazard)
    nhpp = neworder.first_arrival(np.array([0.1, 0.2, 0.3, 0.4, 0.5]), 1.0, 10)
    t.check(isinstance(nhpp, np.ndarray))
    t.check(len(nhpp) == 10)

    return not t.any_failed
Ejemplo n.º 4
0
  def migrations(self, deltat):

    # internal immigrations: 
    # - assign the rates to the incumbent popultion appropriately by age,sex,ethnicity
    # - randomly sample this population, clone and append
    in_rates = self.data.join(self.in_migration, on=["LAD", "NewEthpop_ETH", "DC1117EW_C_SEX", "DC1117EW_C_AGE"])["Rate"].values
    # in-migration should be sampling from the whole population ex-LAD, instead do an approximation by scaling up the LAD population
    # NOTE this is wrong for a number of reasons esp. as it cannot sample category combinations that don't already exist in the LAD
    h_in = neworder.hazard(in_rates * deltat)
    
    incoming = self.data[h_in == 1].copy()

    # Append incomers to main population and adjust counter
    # Assign a new id
    incoming.PID = range(self.counter, self.counter + len(incoming))
    incoming.Area = incoming.LAD
    # assign a new random fractional age based on census age category
    incoming.Age = incoming.DC1117EW_C_AGE - neworder.ustream(len(incoming)).tolist()
    self.data = self.data.append(incoming, sort=False)
    self.counter = self.counter + len(incoming)

    # internal emigration
    out_rates = self.data.join(self.out_migration, on=["LAD", "NewEthpop_ETH", "DC1117EW_C_SEX", "DC1117EW_C_AGE"])["Rate"]
    h_out = neworder.hazard(out_rates.values * deltat)
    # remove outgoing migrants
    self.data = self.data[h_out!=1]

    intl_in_rates = self.data.join(self.immigration, on=["LAD", "NewEthpop_ETH", "DC1117EW_C_SEX", "DC1117EW_C_AGE"])["Rate"]
    h_intl_in = neworder.hazard(intl_in_rates.values * deltat)

    intl_incoming = self.data[h_intl_in == 1].copy()
    intl_incoming.PID = range(self.counter, self.counter + len(intl_incoming))
    intl_incoming.Area = "INTL" #self.lad
    # assign a new random fractional age based on census age category
    intl_incoming.Age = intl_incoming.DC1117EW_C_AGE - neworder.ustream(len(intl_incoming)).tolist()
    self.data = self.data.append(intl_incoming)
    self.counter = self.counter + len(intl_incoming)

    # international emigrtion
    intl_out_rates = self.data.join(self.emigration, on=["LAD", "NewEthpop_ETH", "DC1117EW_C_SEX", "DC1117EW_C_AGE"])["Rate"]
    h_intl_out = neworder.hazard(intl_out_rates.values * deltat)
    # remove outgoing migrants
    self.data = self.data[h_intl_out!=1]

    # record net migration
    self.in_out = (h_in.sum(), h_out.sum(), h_intl_in.sum(), h_intl_out.sum())
Ejemplo n.º 5
0
  def deaths(self, deltat):
    # neworder.log("deaths({:.3f})".format(deltat))

    # Map the appropriate mortality rate to each female
    # might be a more efficient way of generating this array
    rates = self.data.join(self.mortality, on=["LAD", "NewEthpop_ETH", "DC1117EW_C_SEX", "DC1117EW_C_AGE"])["Rate"]

    # Then randomly determine if a birth occurred
    h = neworder.hazard(rates.values * deltat)

    # Finally remove deceased from table
    self.data = self.data[h!=1]
Ejemplo n.º 6
0
    def death(self):
        # construct mortality lookup for the current timestep, means an easy join
        mort = pd.DataFrame({
            "age":
            self.mmort.age,
            "gender":
            np.full(len(self.mmort), True),
            "mortality_rate":
            self.mmort[str(int(neworder.timeline.time()))].values
        })
        mort = mort.append(
            pd.DataFrame({
                "age":
                self.fmort.age,
                "gender":
                np.full(len(self.fmort), False),
                "mortality_rate":
                self.fmort[str(int(neworder.timeline.time()))].values
            }))

        # join the lookup with the people and get each person's mortality rate
        mrates = pd.merge(self.pp, mort, how='left')["mortality_rate"].values

        # scale by timestep
        self.pp["__dead"] = neworder.hazard(mrates * neworder.timestep)

        # record ids of deceased to unlink
        dead_ids = self.pp[self.pp["__dead"] == True].id.values

        # unlink dead mothers
        self.pp.loc[self.pp.mother_id.isin(dead_ids), "mother_id"] = UNSET
        # unlink dead partners
        self.pp.loc[self.pp.partner_id.isin(dead_ids),
                    "civilstate"] = RelationshipStatus.WIDOW.value
        self.pp.loc[self.pp.partner_id.isin(dead_ids), "partner_id"] = UNSET

        #neworder.log("Avg age of men = %f" % np.mean(self.pp[self.pp.gender == True].age))
        neworder.log("Avg age of dead men = %f" %
                     np.mean(self.pp[(self.pp["__dead"] == True)
                                     & (self.pp.gender == True)].age))
        #neworder.log("Avg age of women = %f" % np.mean(self.pp[self.pp.gender == False].age))
        neworder.log("Avg age of dead women = %f" %
                     np.mean(self.pp[(self.pp["__dead"] == True)
                                     & (self.pp.gender == False)].age))
        neworder.log(
            "widows=%d" %
            len(self.pp[self.pp.civilstate == RelationshipStatus.WIDOW.value]))

        # remove deceased
        self.pp = self.pp[self.pp["__dead"] == False]
Ejemplo n.º 7
0
    def divorce(self):
        drate = pd.DataFrame({
            "agegrp":
            self.drate.agegrp,
            "divorce_rate":
            self.drate[str(int(neworder.timeline.time()))].values
        })
        neworder.log(drate)

        # TODO need to map agegrp to age to merge
        drates = pd.merge(self.pp, drate,
                          how='left').fillna(0.0)["fertility_rate"].values

        self.pp["__divorce"] = neworder.hazard(drates * neworder.timestep)

        neworder.log(self.pp)