Python 3.x - iloc 抛出错误 - “单个位置索引器超出范围”

Posted

技术标签:

【中文标题】Python 3.x - iloc 抛出错误 - “单个位置索引器超出范围”【英文标题】:Python 3.x - iloc throws error - "single positional indexer is out-of-bounds" 【发布时间】: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' 你用的是什么版本的熊猫? 【参考方案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

【讨论】:

请解释问题出在哪里以及你做了什么来改变它,而不是仅仅转储代码。谢谢!

以上是关于Python 3.x - iloc 抛出错误 - “单个位置索引器超出范围”的主要内容,如果未能解决你的问题,请参考以下文章

Python 3.x - 从数据框中提取字符串[重复]

错误:“numpy.ndarray”对象没有属性“iloc”

python:pandas之DataFrame取行列(df.loc(),df.iloc())以及索引

python [熊猫] .iloc和.loc

即使在 Pandas 中使用 .iloc 也会出现索引越界错误

python pandas Data.Frame -- iloc和loc以及icol