如何构建字典以实现堆叠DataFrame多列的便捷填充?
Great question! Let's break this down step by step to make filling your DataFrame as smooth as possible—no manual dictionary wrangling required once you set up the right mappings.
Step 1: Automate Match-to-Odds Mapping (No Manual Entry!)
First, instead of manually creating that nested match dictionary (which is error-prone), we can write a simple function to convert your column-specific dictionary lists (like your LB_data) into a clean, reusable mapping. This also fixes any issues with inconsistent team order in your input dictionaries (e.g., if one dict has {'St Kilda': 3.3, 'Essendon': 1.32} but your DataFrame uses "Essendon v St Kilda" as the match key).
Here's the function:
def create_match_odds_map(odds_dicts): """Convert a list of team-odds dicts to a match-to-team-odds mapping.""" match_map = {} for team_odds in odds_dicts: # Sort teams to ensure consistent match keys (e.g., "Essendon v St Kilda" always) sorted_teams = sorted(team_odds.keys()) match_key = f"{sorted_teams[0]} v {sorted_teams[1]}" match_map[match_key] = team_odds return match_map
Use it for all your 4 columns:
# Your original LB data LB_data = [ {'Essendon': 1.32, 'St Kilda': 3.3}, {'Carlton': 5.0, 'Port Adelaide': 1.16}, {'Geelong Cats': 1.57, 'Melbourne': 2.36}, {'Greater Western Sydney': 2.75, 'West Coast Eagles': 1.44}, {'Brisbane': 1.95, 'North Melbourne': 1.85}, {'Hawthorn': 1.38, 'Western Bulldogs': 3.0}, {'Fremantle': 1.32, 'Gold Coast': 3.3} ] # Generate mappings for all 4 columns (replace Odds2_data/Odds3_data/Odds4_data with your actual data) lb_map = create_match_odds_map(LB_data) odds2_map = create_match_odds_map(Odds2_data) odds3_map = create_match_odds_map(Odds3_data) odds4_map = create_match_odds_map(Odds4_data)
Step 2: Fill Your DataFrame (Two Common Scenarios)
Now, how you fill depends on your DataFrame's structure. Let's cover the two most likely cases:
Scenario 1: Your DataFrame has one row per team (stacked format)
If your DataFrame looks like this (each row is a team in a match):
| Match | Team | LB | Odds2 | Odds3 | Odds4 |
|---|---|---|---|---|---|
| Essendon v St Kilda | Essendon | NaN | NaN | NaN | NaN |
| Essendon v St Kilda | St Kilda | NaN | NaN | NaN | NaN |
| Carlton v Port Adelaide | Carlton | NaN | NaN | NaN | NaN |
Use apply() to pull the right odds for each team and match:
import pandas as pd # Replace df with your actual DataFrame df['LB'] = df.apply(lambda row: lb_map.get(row['Match'], {}).get(row['Team']), axis=1) df['Odds2'] = df.apply(lambda row: odds2_map.get(row['Match'], {}).get(row['Team']), axis=1) df['Odds3'] = df.apply(lambda row: odds3_map.get(row['Match'], {}).get(row['Team']), axis=1) df['Odds4'] = df.apply(lambda row: odds4_map.get(row['Match'], {}).get(row['Team']), axis=1)
Scenario 2: Your DataFrame has one row per match (with home/away teams)
If your DataFrame has one row per match with separate columns for home/away teams:
| Match | HomeTeam | AwayTeam | LB_Home | LB_Away | Odds2_Home |
|---|---|---|---|---|---|
| Essendon v St Kilda | Essendon | St Kilda | NaN | NaN | NaN |
Fill directly by referencing the match map and team columns:
# Fill LB column for home/away df['LB_Home'] = df.apply(lambda row: lb_map[row['Match']][row['HomeTeam']], axis=1) df['LB_Away'] = df.apply(lambda row: lb_map[row['Match']][row['AwayTeam']], axis=1) # Repeat for other columns df['Odds2_Home'] = df.apply(lambda row: odds2_map[row['Match']][row['HomeTeam']], axis=1) df['Odds2_Away'] = df.apply(lambda row: odds2_map[row['Match']][row['AwayTeam']], axis=1)
Step 3: Optimize for Large Datasets (Optional)
If you're working with a huge DataFrame, the apply() method might be slow. Instead, create a flattened mapping where the key is a tuple of (Match, Team) for faster lookups:
def create_flat_odds_map(match_map): flat_map = {} for match, team_odds in match_map.items(): for team, odd in team_odds.items(): flat_map[(match, team)] = odd return flat_map # Create flattened maps for all columns lb_flat = create_flat_odds_map(lb_map) odds2_flat = create_flat_odds_map(odds2_map) # Fill using tuple keys (much faster for large data) df['LB'] = df.apply(lambda row: lb_flat.get((row['Match'], row['Team'])), axis=1)
Key Takeaways
- Automate mappings: Never manually write match dictionaries—use the
create_match_odds_mapfunction to avoid typos and handle team order inconsistencies. - Choose the right fill method: Use
apply()for small datasets, or flattened mappings for large ones. - Scale easily: This approach works for all 4 of your columns—just repeat the mapping and filling steps for each.
内容的提问来源于stack exchange,提问作者RJM

