【问题标题】:Python 3.x - iloc throws error - "single positional indexer is out-of-bounds"Python 3.x - iloc 抛出错误 - “单个位置索引器超出范围”
【发布时间】:2016-10-23 20:59:59
【问题描述】:

我正在从网站上抓取选举数据并尝试将其存储在数据框中

import pandas as pd
import bs4
import requests

columns = ['Candidate','Party','Criminal Cases','Education','Age','Total Assets','Liabilities']

df = pd.DataFrame(columns = columns)

ind=1

url = requests.get("http://myneta.info/up2007/index.php?action=show_candidates&constituency_id=341")
soup = bs4.BeautifulSoup(url.content)

for content in soup.findAll("td")[16:]:
    df.iloc[ind//7,ind%7-1] = content.text
    ind=ind+1
print(df)

基本上,content.text 的每次迭代都会为我提供一个值,我将在表格中填充该值。循环将按以下顺序将值填充到 df -

df[0,0]
df[0,1]
df[0,2]
.
.
.
df[1,0]
df[1,1]
.
.

等等。不幸的是,iloc 抛出了一个错误——“单个位置索引器越界”。有趣的是,当我在 for 循环之外尝试 df.iloc[0,0] = content.text 时(在一个单独的单元格中用于测试目的),代码可以正常工作,但在 for 循环中它会产生错误。我相信这可能是微不足道的,但我无法理解。请帮助

【问题讨论】:

  • 在询问为什么一段代码不工作时包括回溯(如果有的话)。 ind%7-1 将为 7 生成 -1,这可能会让你失望。另外,您的示例是否完整? DataFrame.iloc 甚至不应该能够附加数据(或者我在你的例子中遗漏了一些东西)。
  • @IljaEverilä 我同意,但这将在 for 循环运行 6 次后发生。问题是它甚至没有运行一次。我有一个处理'ind = 7'的逻辑,但要达到那个逻辑,'ind = 1,2 ...'需要先运行
  • 问题仍然存在,使用iloc 您不应该能够附加到DataFrame。您的 df 最初为空。
  • 让我更简单地解释一下。问题最终归结为这类问题 - ' df1 = pd.DataFrame(columns= ['a','b','c']) df1.iloc[0,0]=1 - # 不起作用 输出- 单个位置索引器超出范围 df1.loc[0,'a']=1 - # Works print(df1) 输出 abc 0 1 NaN NaN'
  • 你用的是什么版本的熊猫?

标签: python indexing dataframe web-scraping


【解决方案1】:

DataFrame.iloc 无法放大其目标对象。这曾经是错误消息,但自 0.15 版以来已更改。

一般而言,DataFrame 并不意味着一次构建一行。这是非常低效的。相反,您应该创建一个更传统的数据结构并从中填充 DataFrame

table = soup.find(id='table1')
rows = table.find_all('tr')[1:]
data = [[cell.text for cell in row.find_all('td')] for row in rows]
df = pd.DataFrame(data=data, columns=columns)

通过检查您请求中的页面,您似乎在使用 id 为“table1”的表之后,该表的第一行是标题(该页面作者的一个糟糕的选择,应该在 @987654325 @,不是正文)。所以跳过第一行 ([1:]),然后从行的单元格构建一个列表列表。

当然,你也可以让 pandas 自己操心解析等等:

url = "http://myneta.info/up2007/index.php?action=show_candidates&constituency_id=341"
df = pd.read_html(url, header=0)[2]  # Pick the 3rd table in the page

【讨论】:

    【解决方案2】:

    这是一种解决方法。我的 pandas 版本出现相同的 iloc 错误。修改后的代码通过在每次迭代之前创建一个空白记录(通过创建一个 1 行数据框并附加到现有的数据框)来克服它,然后再为它们分配值。

    import pandas as pd
    import bs4
    import requests
    
    columns = ['Candidate','Party','Criminal Cases','Education','Age','Total Assets','Liabilities']
    
    df = pd.DataFrame(columns = columns)
    
    ind=1
    url = requests.get("http://myneta.info/up2007/index.php?action=show_candidates&constituency_id=341")
    soup = bs4.BeautifulSoup(url.content)
    
    for content in soup.findAll("td")[16:]:
        data = pd.DataFrame({columns[0]:"",
                         columns[1]:"",
                         columns[2]:"",
                         columns[3]:"",
                         columns[4]:"",
                         columns[5]:"",
                         columns[6]:"",
                        },index=[0])
        df=df.append(data,,ignore_index=True)
        df.iloc[ind//7,ind%7-1] = content.text
        ind=ind+1
    

    【讨论】:

    • 请解释问题出在哪里以及你做了什么来改变它,而不是仅仅转储代码。谢谢!
    猜你喜欢
    • 2017-08-02
    • 2020-11-26
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多