def apply_final_rules(hh_util, people, hh_id_col, final_rules):
    rule_mask = eval_variables(final_rules.index, people)

    if not rule_mask.as_matrix().any():
        # if the rules don't apply to anyone then return now
        return

    alt_match_cache = {}

    for hh_id, df in people.groupby(hh_id_col, sort=False):
        mask = rule_mask.loc[df.index]
        if not mask.as_matrix().any():
            # if the mask doesn't apply to anyone in this household
            # carry on to the next household
            continue

        utils = hh_util[hh_id]
        hh_size = len(df)

        for exp, row in final_rules.iterrows():
            m = mask[exp].as_matrix()
            if not m.any():
                # if this sub-mask doesn't apply to anyone here then
                # carry on to the next rule
                continue

            # this crazy business combines three things to figure out
            # which household alternatives need to be modified by this rule.
            # the three things are:
            # - the mask of people for whom the rule expression is true (m)
            # - the individual alternative to which the rule applies
            #   (alt)
            # - the alternative combinations for the household
            #   (utils.index)
            alt = row.iloc[0]
            key = (alt, hh_size)
            if key in alt_match_cache:
                alt_match = alt_match_cache[key]
            else:
                alt_match = np.array(utils.index.values.tolist()) == alt
                alt_match_cache[key] = alt_match

            app = np.any(np.bitwise_and(alt_match, m), axis=1)

            utils[app] = row.iloc[1]
Given a raw message of metrics split by newline characters, this will
dataset/ETHPy150Open UDST/activitysim/activitysim/cdap/cdap.py/apply_final_rules--crossover with--dataset/ETHPy150Open kiip/statsite/statsite/collector.py/Collector._parse_metrics