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 抛出错误 - “单个位置索引器超出范围”的主要内容,如果未能解决你的问题,请参考以下文章
错误:“numpy.ndarray”对象没有属性“iloc”
python:pandas之DataFrame取行列(df.loc(),df.iloc())以及索引