You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python数据分析遇KeyError:指定索引项不在DataFrame列中求解决

KeyError错误分析与修复方案

错误原因

  1. 无效的Series操作:代码中summary - summary[base_cols]是无意义的减法运算,没有对summary做任何筛选或修改,导致summary保留了所有重复索引项。后续合并时,这些索引被转为列名,而base_cols是索引值,自然找不到对应的列,触发KeyError。
  2. 拼写错误:pandas.concat(summaries, asix=1).T里的asix是笔误,正确应为axis=1。这个错误会导致合并方向完全错误,把本应按列合并的操作变成按行合并,最终数据结构完全不符合预期。
  3. 参数传递错误:调用read_season_info("soup")时传了字符串soup,而非解析后的BeautifulSoup对象,这会导致获取赛季信息失败,引发额外错误。

修复步骤

  • 替换无效操作:把summary - summary[base_cols]改为按索引筛选并赋值:
    summary = summary[base_cols]
    
    这一步确保summary只保留我们需要的、去重后的统计项。
  • 修正拼写错误:将asix=1改为axis=1:
    summary = pandas.concat(summaries, axis=1).T
    
  • 修复参数传递:把read_season_info("soup")改为传递实际的soup对象:
    full_game["season"] = read_season_info(soup)
    

修正后的完整代码

from bs4 import BeautifulSoup
import pandas
import os

SEASONS = list(range(2016, 2017))
DATA_DIR = "data"
STANDINGS_DIR = os.path.join(DATA_DIR, "standings")
SCORES_DIR = os.path.join(DATA_DIR, "scores")

box_scores = os.listdir(SCORES_DIR)
box_scores = [os.path.join(SCORES_DIR, f) for f in box_scores if f.endswith(".html")]

def parse_html(box_score):
    with open(box_score) as f:
        html = f.read()

    soup = BeautifulSoup(html)
    [s.decompose() for s in soup.select("tr.over_header")]
    [s.decompose() for s in soup.select("tr.thead")]
    return soup

def read_line_score(soup):
    line_score = pandas.read_html(str(soup), attrs = {"id": "line_score"})[0]
    cols = list(line_score.columns)
    cols[0] = "team"
    cols[-1] = "total"
    line_score.columns = cols

    line_score = line_score[["team", "total"]]
    return line_score


def read_stats(soup, team, stat):
    df = pandas.read_html(str(soup), attrs={"id": f"box-{team}-game-{stat}"}, index_col=0)[0]
    df = df.apply(pandas.to_numeric, errors="coerce")
    return df

def read_season_info(soup):
    nav = soup.select("#bottom_nav_container")[0]
    hrefs = [a["href"] for a in nav.find_all("a")]
    season = os.path.basename(hrefs[1]).split("_")[0]
    return season

base_cols = None
games = []

for box_score in box_scores:
    soup = parse_html(box_score)
    line_score = read_line_score(soup)
    teams = list(line_score["team"])

    summaries = []
    for team in teams:
        basic = read_stats(soup, team, "basic")
        advanced = read_stats(soup, team, "advanced")

        totals = pandas.concat([basic.iloc[-1:], advanced.iloc[-1:]])
        totals.index = totals.index.str.lower()

        maxes = pandas.concat([basic.iloc[:-1,:].max(), advanced.iloc[:-1,:].max()])
        maxes.index = maxes.index.str.lower() + "_max"

        summary = pandas.concat([totals, maxes])

        if base_cols is None:
            base_cols = list(summary.index.drop_duplicates(keep="first"))
            base_cols = [b for b in base_cols if "bpm" not in b]

        # 修复:替换无效减法为索引筛选
        summary = summary[base_cols]

        summaries.append(summary)

    # 修复:修正axis拼写错误
    summary = pandas.concat(summaries, axis=1).T

    game = pandas.concat([summary, line_score], axis=1)

    game["home"] = [0, 1]
    game_opp = game.iloc[::-1].reset_index()
    game_opp.columns += "_opp"

    full_game = pandas.concat([game, game_opp], axis=1)

    # 修复:传递正确的soup对象
    full_game["season"] = read_season_info(soup)

    full_game["date"] = os.path.basename(box_score)[:8]
    full_game["date"] = pandas.to_datetime(full_game["date"], format="%Y%m%d")

    full_game["won"] = full_game["total"] > full_game["total_opp"]

    games.append(full_game)

    if len(games) % 100 == 0:
        print(f"{len(games)} / {len(box_scores)}")

内容的提问来源于stack exchange,提问作者pynewbpy44

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:01:05