【问题标题】:Python Appending DataFrame, weird for loop errorPython附加DataFrame,奇怪的循环错误
【发布时间】:2020-01-28 19:07:25
【问题描述】:

我正在做一些 NFL 统计数据网页抓取,老实说,这项活动并不重要。我花了很多时间调试,因为我无法相信它在做什么,要么我快疯了,要么包或 python 本身存在某种错误。这是我正在使用的代码:

import pandas as pd
from bs4 import BeautifulSoup as bs
import requests
import string
import numpy as np

#get player list
players = pd.DataFrame({"name":[],"url":[],"positions":[],"startYear":[],"endYear":[]})
letters = list(string.ascii_uppercase)
for letter in letters:
    print(letter)
    players_html = requests.get("https://www.pro-football-reference.com/players/"+letter+"/")
    soup = bs(players_html.content,"html.parser")
    for player in soup.find("div",{"id":"div_players"}).find_all("p"):
        temp_row = {}
        temp_row["url"] = "https://www.pro-football-reference.com"+player.find("a")["href"]
        temp_row["name"] = player.text.split("(")[0].strip()
        years = player.text.split(")")[1].strip()
        temp_row["startYear"] = int(years.split("-")[0])
        temp_row["endYear"] = int(years.split("-")[1])
        temp_row["positions"] = player.text.split("(")[1].split(")")[0]
        players = players.append(temp_row,ignore_index=True)
players = players[players.endYear > 2000]
players.reset_index(inplace=True,drop=True)

game_df = pd.DataFrame()
def apply_test(row):
    #print(row)
    url = row['url']
    #print(list(range(int(row['startYear']),int(row['endYear'])+1)))
    for yr in range(int(row['startYear']),int(row['endYear'])+1):
        print(yr)
        content = requests.get(url.split(".htm")[0]+"/gamelog/"+str(yr)).content
        soup = bs(content,'html.parser').find("div",{"id":"all_stats"})
        #overheader
        over_headers = []
        for over in soup.find("thead").find("tr").find_all("th"):
            if("colspan" in over.attrs.keys()):
                for i in range(0,int(over['colspan'])):
                    over_headers = over_headers + [over.text]
            else:
                over_headers = over_headers + [over.text]
        #headers
        headers = []
        for header in soup.find("thead").find_all("tr")[1].find_all("th"):
            headers = headers + [header.text]
        all_headers = [a+"___"+b for a,b in zip(over_headers,headers)]
        #remove first column, it's meaningless
        all_headers = all_headers[1:len(all_headers)]
        for row in soup.find("tbody").find_all("tr"):
            temp_row = {}
            for i,col in enumerate(row.find_all("td")):
                temp_row[all_headers[i]] = col.text
            game_df = game_df.append(temp_row,ignore_index=True)
players.apply(apply_test,axis=1)


现在我可以再次进入我正在尝试做的事情,但这里似乎有一个更高级别的问题。 for 循环中的 startYear 和 endYear 是 2013 年和 2014 年,因此循环应该将 yr 变量设置为 2013 年,然后是 2014 年。但是当您查看由于print(yr) 而打印出的内容时,您会意识到它打印出 2013 两次。但是,如果您只是注释掉 game_df = game_df.append(temp_row,ignore_index=True) 行,则 yr 的打印输出是正确的。在前两行之后不久有一个错误,但这是意料之中的,而且我很乐意调试。但是,附加到全局数据框会导致 for 循环的行为不同,这一事实现在让我大吃一惊。有人可以帮忙吗?

谢谢。

【问题讨论】:

    标签: python pandas loops for-loop append


    【解决方案1】:

    我并没有真正遵循总体目标是什么,但我确实注意到了两件事:

      1234563 /p>
    1. 您需要处理 find 返回 None 的情况,例如soup.find("thead").find_all("tr")[1].find_all("th") 用于页面 https://www.pro-football-reference.com/players/A/AaitIs00/gamelog/2014。或许可以在 try except 块中添加适当的默认值。

    【讨论】:

    • 是的,检查无是正常的,我知道如何解决这个问题。对于全局变量,我有点困惑,我认为在函数外部定义的变量默认是全局的。 python中有全局标签吗?另一个问题是为什么变量是全局变量还是不会导致 for 循环的行为不同?谢谢。
    • 是的,它导致了不同的行为,并且代码将您的 def 中的 game_df 视为局部变量,因为您没有使用 global 关键字,并且在分配之前也被引用。至少这是我的解释,但我对 Python 还是很陌生。
    • 一些快速的谷歌搜索表明,我不相信 global 是你必须在 python 中声明的实际事物。没有全局关键字,并且考虑到我在任何函数之外定义了 DataFrame,默认情况下它应该是全局的。我仍然看不出任何此类问题如何可能导致 for 循环在两次迭代中都有 yr=2013,尽管它应该是 2013 年和 2014 年。
    • geeksforgeeks.org/global-local-variables-python 第一个谷歌结果,python 更改函数中的全局变量
    • 哦,有趣的是,我认为 python 充当其他语言,例如 js,如果它没有在本地范围内定义,它会意识到它是全局的。我在函数的开头添加了 global game_df 并且它起作用了。我想我需要做一些阅读。谢谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 2021-05-13
    • 2023-03-27
    相关资源
    最近更新 更多