2016-06-22 11 views
4

I Wahldaten von einer Website bin Schaben und versuchen, es zu speichern, in einem DatenrahmenPython 3.x - ILoc wirft Fehler - "Einzelpositions Indexer ist out-of-bounds"

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) 

Im Wesentlichen jede Iteration von content.text liefert mir einen Wert, den ich in der Tabelle auffüllen werde. Die Schleife wird Wert füllen in der folgenden Reihenfolge df -

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

und so weiter. Leider wirft das Iloc einen Fehler - "ein einzelner Positionsindexer ist außerhalb der Grenzen". Der lustige Teil ist, wenn ich df.iloc[0,0] = content.text außerhalb der for-Schleife (in einer separaten Zelle für Testzweck) versuchen, funktioniert der Code ordnungsgemäß, aber in der for-Schleife erstellt es einen Fehler. Ich glaube, es könnte etwas trivial sein, aber ich kann nicht verstehen. Bitte helfen

+0

die Zurückverfolgungs einschließen, wenn fragen, warum ein Stück Code funktioniert nicht, wenn Sie bekommen. 'ind% 7-1' erzeugt' -1' für 7, was Sie wahrscheinlich abschrecken wird. Ist Ihr Beispiel abgeschlossen? 'DataFrame.iloc' sollte nicht einmal Daten anhängen können (oder ich habe in Ihrem Beispiel etwas verpasst). –

+0

@ IljaEverilä ich stimme zu, aber das wird passieren, nachdem die for-Schleife 6 Mal ausgeführt wurde. Das Problem ist, dass es nicht einmal läuft. Ich habe eine Logik, um 'ind = 7' zu handhaben, aber um zu dieser Logik zu gelangen, muss 'ind = 1,2 ...' zuerst laufen –

+0

Das Problem besteht immer noch darin, dass 'iloc' nicht in der Lage sein sollte Anhängen an einen 'DataFrame'. Dein 'df' ist anfangs leer. –

Antwort

12

DataFrame.iloc kann sein Zielobjekt nicht vergrößern. Dies war früher die Fehlermeldung, hat sich aber seit Version 0.15 geändert.

Im Allgemeinen ist eine DataFrame nicht dazu gedacht, Zeile für Zeile zu erstellen. Es ist sehr ineffizient. Stattdessen sollten Sie eine traditionellere Datenstruktur erstellen und füllen ein DataFrame davon:

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) 

Von der Seite in Ihrer Anfrage Inspektion es scheint, dass Sie mit der ID „table1“ nach der Tabelle waren, die als erste Zeile hat der Header (eine schlechte Wahl von den Autoren dieser Seite, sollte in <thead> gewesen sein, nicht der Körper). Überspringen Sie also die erste Zeile ([1:]) und erstellen Sie dann eine Liste von Listen aus den Zellen der Zeilen.

Natürlich können Sie auch einfach lassen Pandas Sorgen über das Parsen und alle:

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 
0

Dies ist eine Problemumgehung. Ich bekomme den gleichen iloc Fehler mit meiner Pandas Version. Dieser geänderte Code überwindet ihn, indem er einen leeren Datensatz erstellt (indem er einen 1-reihigen Datenframe erstellt und an den vorhandenen anhängt), bevor jede Iteration Werte zugewiesen werden.

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 
+1

Bitte erläutern Sie, was das Problem war und was Sie getan haben, um es zu ändern, anstatt nur den Code zu löschen. Vielen Dank! –