Skip to content

Commit

Permalink
ratio -> multiplier for clarity
Browse files Browse the repository at this point in the history
  • Loading branch information
jiffyclub committed Oct 2, 2014
1 parent 2390122 commit 34b90d8
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 41 deletions.
55 changes: 28 additions & 27 deletions urbansim/models/supplydemand.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
logger = logging.getLogger(__name__)


def _calculate_adjustment_ratio(
def _calculate_adjustment(
lcm, choosers, alternatives, alt_segmenter,
clip_change_low, clip_change_high):
"""
Expand All @@ -34,12 +34,12 @@ def _calculate_adjustment_ratio(
Returns
-------
ratio : pandas.Series
Index is unique values from `alt_segmenter`, values are the ratio
for each segment in `alt_segmenter`.
alt_idx_ratio : pandas.Series
alts_muliplier : pandas.Series
Same index as `alternatives`, values clipped to `clip_change_low`
and `clip_change_high`.
submarkets_multiplier : pandas.Series
Index is unique values from `alt_segmenter`, values are the ratio
of demand / supply for each segment in `alt_segmenter`.
"""
logger.debug('start: calculate supply and demand price adjustment ratio')
Expand All @@ -51,21 +51,22 @@ def _calculate_adjustment_ratio(
# number of alternatives
supply = alt_segmenter.value_counts()

ratio = (demand / supply).clip(clip_change_low, clip_change_high)
multiplier = (demand / supply).clip(clip_change_low, clip_change_high)

# broadcast ratio back to alternatives index
alt_idx_ratio = ratio.loc[alt_segmenter]
alt_idx_ratio.index = alt_segmenter.index
# broadcast multiplier back to alternatives index
alts_muliplier = multiplier.loc[alt_segmenter]
alts_muliplier.index = alt_segmenter.index

logger.debug(
('finish: calculate supply and demand price adjustment ratio '
'with mean ratio {}').format(ratio.mean()))
return alt_idx_ratio, ratio
('finish: calculate supply and demand price adjustment multiplier '
'with mean multiplier {}').format(multiplier.mean()))
return alts_muliplier, multiplier


def supply_and_demand(
lcm, choosers, alternatives, alt_segmenter, price_col, base_ratio=None,
clip_change_low=0.75, clip_change_high=1.25, iterations=5):
lcm, choosers, alternatives, alt_segmenter, price_col,
base_multiplier=None, clip_change_low=0.75, clip_change_high=1.25,
iterations=5):
"""
Adjust real estate prices to compensate for supply and demand effects.
Expand All @@ -84,7 +85,7 @@ def supply_and_demand(
price_col : str
The name of the column in `alternatives` that corresponds to price.
This column is what is adjusted by this model.
base_ratio : pandas.Series, optional
base_multiplier : pandas.Series, optional
A series describing a starting multiplier for submarket prices.
Index should be submarket IDs.
clip_change_low : float, optional
Expand All @@ -99,9 +100,9 @@ def supply_and_demand(
new_prices : pandas.Series
Equivalent of the `price_col` in `alternatives`.
submarkets_ratios : pandas.Series
Price adjustment ratio for each submarket. If `base_ratio` is given
this will be a cummulative multiplier including the `base_ratio`
and the multipliers calculated for this year.
Price adjustment ratio for each submarket. If `base_multiplier` is
given this will be a cummulative multiplier including the
`base_multiplier` and the multipliers calculated for this year.
"""
logger.debug('start: calculating supply and demand price adjustment')
Expand All @@ -115,20 +116,20 @@ def supply_and_demand(
alt_segmenter = pd.Series(alt_segmenter)

# check base ratio and apply it to prices if given
if base_ratio is not None:
br = base_ratio.loc[alt_segmenter]
br.index = alt_segmenter.index
alternatives[price_col] = alternatives[price_col] * br
if base_multiplier is not None:
bm = base_multiplier.loc[alt_segmenter]
bm.index = alt_segmenter.index
alternatives[price_col] = alternatives[price_col] * bm

for _ in range(iterations):
alt_idx_ratio, submarkets_ratio = _calculate_adjustment_ratio(
alts_muliplier, submarkets_multiplier = _calculate_adjustment(
lcm, choosers, alternatives, alt_segmenter,
clip_change_low, clip_change_high)
alternatives[price_col] = alternatives[price_col] * alt_idx_ratio
alternatives[price_col] = alternatives[price_col] * alts_muliplier

# if we started with a base ratio, return a cumulative ratio
if base_ratio is not None:
submarkets_ratio *= base_ratio
if base_multiplier is not None:
submarkets_multiplier *= base_multiplier

logger.debug('finish: calculating supply and demand price adjustment')
return alternatives[price_col], submarkets_ratio
return alternatives[price_col], submarkets_multiplier
28 changes: 14 additions & 14 deletions urbansim/models/tests/test_supplydemand.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,27 @@ def lcm():
return _TestLCM()


def test_calculate_adjustment_ratio_clips(
def test_calculate_adjustment_clips(
lcm, choosers, alternatives, alt_segmenter):
clip = 1

alt_ratio, submarket_ratio = supdem._calculate_adjustment_ratio(
alts_multiplier, submarkets_multiplier = supdem._calculate_adjustment(
lcm, choosers, alternatives, alternatives[alt_segmenter], clip, clip)

pdt.assert_series_equal(
alt_ratio, pd.Series([1] * 10, index=alternatives.index),
alts_multiplier, pd.Series([1] * 10, index=alternatives.index),
check_dtype=False)
pdt.assert_series_equal(
submarket_ratio, pd.Series([1] * 4, index=['w', 'x', 'y', 'z']),
submarkets_multiplier, pd.Series([1] * 4, index=['w', 'x', 'y', 'z']),
check_dtype=False)


def test_calculate_adjustment_ratio(
def test_calculate_adjustment(
lcm, choosers, alternatives, alt_segmenter):
clip_low = 0
clip_high = 2

alt_ratio, submarket_ratio = supdem._calculate_adjustment_ratio(
alts_multiplier, submarkets_multiplier = supdem._calculate_adjustment(
lcm, choosers, alternatives, alternatives[alt_segmenter],
clip_low, clip_high)

Expand All @@ -71,11 +71,11 @@ def test_calculate_adjustment_ratio(
z = 3 / 2

pdt.assert_series_equal(
alt_ratio,
alts_multiplier,
pd.Series([w, x, y, z, z, x, y, w, y, y],
index=alternatives.index))
pdt.assert_series_equal(
submarket_ratio,
submarkets_multiplier,
pd.Series([w, x, y, z], index=['w', 'x', 'y', 'z']))


Expand All @@ -90,7 +90,7 @@ def test_supply_and_demand(
y = 1.25
z = 3 / 2

new_price, submarket_ratio = supdem.supply_and_demand(
new_price, submarkets_multiplier = supdem.supply_and_demand(
lcm, choosers, alternatives, alt_segmenter, price_col,
clip_change_low=clip_low, clip_change_high=clip_high)

Expand All @@ -100,7 +100,7 @@ def test_supply_and_demand(
[w, x, y, z, z, x, y, w, y, y],
index=alternatives.index) ** 5)
pdt.assert_series_equal(
submarket_ratio,
submarkets_multiplier,
pd.Series([w, x, y, z], index=['w', 'x', 'y', 'z']))


Expand All @@ -115,17 +115,17 @@ def test_supply_and_demand_base_ratio(
y = 1.25
z = 3 / 2

base_ratio = pd.Series([w, x, y, z], index=['w', 'x', 'y', 'z'])
base_multiplier = pd.Series([w, x, y, z], index=['w', 'x', 'y', 'z'])

new_price, submarket_ratio = supdem.supply_and_demand(
new_price, submarkets_multiplier = supdem.supply_and_demand(
lcm, choosers, alternatives, alt_segmenter, price_col,
base_ratio, clip_low, clip_high)
base_multiplier, clip_low, clip_high)

pdt.assert_series_equal(
new_price,
pd.Series(
[w, x, y, z, z, x, y, w, y, y],
index=alternatives.index) ** 6)
pdt.assert_series_equal(
submarket_ratio,
submarkets_multiplier,
pd.Series([w, x, y, z], index=['w', 'x', 'y', 'z']) ** 2)

0 comments on commit 34b90d8

Please sign in to comment.