Car Shopping Solution¶
all_fair_prices = fair_prices.loc[asking_prices.index]
off_market_prices = asking_prices - all_fair_prices
below_fair_prices = (off_market_prices < 0).reset_index(drop=True)
below_fair_prices.loc[below_fair_prices].index.to_list()
# [0, 4]
Explanation¶
Your first instinct may be to do asking_prices - fair_prices
. In fact, Pandas uses the index labels to subtract
the correct fair_prices
from each asking_price
.
# camry 1500
# civic -500
# civic 2100
# mustang 1000
# mustang -500
# dtype: int64
Unfortunately the resulting Series gets reordered by the index in alphabetical order, so we lose track of which (asking price, fair price) is represented by each row.
An alternative strategy is, "for each asking price, get the corresponding fair price". We can accomplish this with
fair_prices.loc[]
passing in the index labels from asking_prices
. We'll store the result in a variable
called all_fair_prices.
all_fair_prices = fair_prices.loc[asking_prices.index]
print(all_fair_prices)
# civic 5500
# civic 5500
# camry 7500
# mustang 7500
# mustang 7500
# dtype: int64
Next, we calculate how far off each fair price is from the asking price.
off_market_prices = asking_prices - all_fair_prices
print(off_market_prices)
civic -500
civic 2100
camry 1500
mustang 1000
mustang -500
dtype: int64
The good deals are the negative values in this Series.
Next we set below_fair_prices = off_market_prices < 0
to get a boolean series indicating
whether each car for sale is below its fair price.
below_fair_prices = off_market_prices < 0
below_fair_prices
# civic True
# civic False
# camry False
# mustang False
# mustang True
# dtype: bool
We'll also chain that with .reset_index(drop=True)
to make the index a RangeIndex like [0, 1, 2, 3, 4]
.
below_fair_prices = (off_market_prices < 0).reset_index(drop=True)
below_fair_prices
# 0 True
# 1 False
# 2 False
# 3 False
# 4 True
# dtype: bool
Now our goal is to pick out the indices corresponding to True values - in this case 0 and 4.
If we do below_fair_prices.loc[below_fair_prices]
, we'll get back the subseries with just True elements.
below_fair_prices.loc[below_fair_prices]
# 0 True
# 4 True
# dtype: bool
and then we can chain that with .index.to_list()
to get back the index values in list.
below_fair_prices.loc[below_fair_prices].index.to_list()
# [0, 4]