Skip to content

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]

See the problem