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

Python新手求助:如何用列表替代数组构建正确格式的两年份统计数据集

解决NBA选秀数据合并的问题

嘿,作为Python新手碰到这种数据拼接的问题太正常了,我来帮你捋清楚怎么搞定!

你的核心问题是:现在的代码把每一年的表格作为单独的二维数组加到table列表里,最后转成DataFrame时,就变成了“每行对应一整年的数据”,而不是你想要的“所有年份的数据上下连续排列”。

最简单的解决方案:用Pandas直接读取HTML表格

篮球参考(Basketball Reference)的页面表格结构非常规范,Pandas自带的read_html函数可以直接帮你抓取表格,完全不用手动解析HTML,省超多事!

import pandas as pd

# 初始化空DataFrame用来存放所有年份的数据
final_data = pd.DataFrame()

# 遍历1956和1957年(注意range是左闭右开,所以1958刚好到1957年结束)
for draft_year in range(1956, 1958):
    url = f"https://www.basketball-reference.com/draft/NBA_{draft_year}.html#stats::none"
    # 抓取页面中的第一个表格(就是选秀数据表格)
    year_table = pd.read_html(url)[0]
    # 给当前年份的表格加一列年份,方便后续区分数据来源
    year_table['Draft Year'] = draft_year
    # 把当前年份的表格拼接到最终数据里
    final_data = pd.concat([final_data, year_table], ignore_index=True)

# 保存到CSV文件,去掉自动生成的索引列
final_data.to_csv("nba_draft_stats.csv", index=False)

如果你想坚持用BeautifulSoup解析

如果你还是想自己用BeautifulSoup处理HTML,那我们需要调整数据收集的方式:不要把每一年的表格作为单独元素加到列表,而是按行收集所有年份的数据,最后统一转成DataFrame。

修正后的代码:

import bs4
from bs4 import BeautifulSoup
from urllib.request import urlopen
import pandas as pd

# 初始化一个大列表,用来存放所有行的数据(所有年份的行都会存在这里)
all_rows = []

for draft_year in range(1956, 1958):
    url = f"https://www.basketball-reference.com/draft/NBA_{draft_year}.html#stats::none"
    soup = BeautifulSoup(urlopen(url), "html.parser")
    
    # 获取表头(可选,但加上后CSV会有清晰的列名)
    header_cells = soup.find("tr", class_="thead").find_all("th")
    column_names = [cell.text.strip() for cell in header_cells if cell.text.strip()]
    # 加上年份列的名字
    column_names.append("Draft Year")
    
    # 遍历所有数据行(页面里的full_table和partial_table类都是有效数据行)
    data_rows = soup.find_all("tr", class_=["full_table", "partial_table"])
    for row in data_rows:
        # 提取当前行的所有内容:先取<th>里的顺位,再取<td>里的其他数据
        row_content = [cell.text.strip() for cell in row.find_all("th") if cell.text.strip()]
        row_content.extend([cell.text.strip() for cell in row.find_all("td")])
        # 把当前年份加到行末尾
        row_content.append(str(draft_year))
        # 把这一行数据加入大列表
        all_rows.append(row_content)

# 把大列表转成DataFrame
final_data = pd.DataFrame(all_rows, columns=column_names)
# 保存到CSV
final_data.to_csv("nba_draft_stats.csv", index=False)

为什么原来的代码不对?

你之前的代码里,每次循环把mtable3(单个年份的二维数组)append到table里,最后table是一个包含两个二维数组的列表。当你用pd.DataFrame(table)转换时,Pandas会把每个二维数组当成一行的元素,自然不是你要的上下排列格式。而现在的方法是把所有行数据都放到一个列表里,转成DataFrame就是连续的表格啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 10:42:45