Search code examples
pandasidioms

How can I make this code into more idiomatic pandas?


Kind of a broad question, but I am not sure how else to get pointers on how to improve this code.

I have a dataframe which has betting odds and game results, and I would like to compute the payout of investing in a certain team.

The code I have now works, but I feel like it skimps on much of what Pandas can do by just leaning on the apply method and dropping into Python.

Here's what the dataframe looks like: enter image description here

And here is my code:

def compute_payout(odds, amount=1):
    if odds < 0:
        return amount/(-1.0 * odds/100.0)
    elif odds > 0:
        return amount/(100.0/odds)

def game_payout(row, team_name):
    if row['home_team'] == team_name:
        if row['home_score'] > row['away_score']:
            return compute_payout(row['home_odds'])
        else:
            return -1
    elif row['away_team'] == team_name:
        if row['away_score'] > row['home_score']:
            return compute_payout(row['away_odds'])
        else:
            return -1

payout = df.apply(lambda row: game_payout(row, team_name), axis=1)

Any suggestions are deeply appreciated!


Solution

  • Use numpy.select with conditions chained by & for bitwise AND and ~ for invert boolean mask:

    m11 = df['home_team'] == team_name
    m21 = df['away_team'] == team_name
    
    m12 = df['home_score'] > df['away_score']
    m22 = df['home_score'] < df['away_score']
    
    vals = [df['home_odds'].apply(compute_payout), -1, df['away_odds'].apply(compute_payout), -1]
    payout = np.select([m11 & m12, m11 & ~m12, m21 & m22, m21 & ~m22], vals, default=np.nan)