2016-07-29 13 views
1

Ich habe einen Datenrahmen, den ich von Basketball-Referenz mit Spielernamen genommen habe. Der Code unten ist wie ich den DataFrame gebaut habe. Es hat 5 Spalten mit Spielernamen, aber jeder Name hat auch die Position des Spielers.Warum funktioniert eine Spalte von pandas DataFrame nicht in dieser Schleife?

url = "http://www.basketball-reference.com/awards/all_league.html" 
dframe_list = pd.io.html.read_html(url) 
df = dframe_list[0] 
df.drop(df.columns[[0,1,2]], inplace=True, axis=1) 
column_names = ['name1', 'name2', 'name3', 'name4', 'name5'] 
df.columns = column_names 
df = df[df.name1.notnull()] 

Ich versuche, die Position abzuspalten. Um dies zu tun hatte ich geplant, um einen Datenrahmen für jeden Namen Spalte zu machen:

name1 = pd.DataFrame(df.name1.str.split().tolist()).ix[:,0:1] 
name1[0] = name1[0] + " " + name1[1] 
name1.drop(name1.columns[[1]], inplace=True, axis=1) 

Seit ich fünf Spalten habe ich dachte, ich würde dies tun, mit einer Schleife

column_names = ['name1', 'name2', 'name3', 'name4', 'name5'] 
for column in column_names: 
    column = pd.DataFrame(df.column.str.split().tolist()).ix[:,0:1] 
    column[0] = column[0] + " " + column[1] 
    column.drop(column.columns[[1]], inplace=True, axis=1) 
    column.columns = column 

Und dann würde ich komme alle diese DataFrames wieder zusammen.

df_NBA = [name1, name2, name3, name4, name5] 
df_NBA = pd.concat(df_NBA, axis=1) 

Ich bin neu in Python, also bin ich sicher, dass ich dies in einem ziemlich umständliche Art und Weise zu tun und würden Vorschläge lieben, wie ich dies schneller tun könnte. Aber meine Hauptfrage ist, wenn ich den Code auf einzelne Spalten führen Sie es funktioniert gut, aber wenn, wenn ich die Schleife betreibe ich den Fehler:

AttributeError: 'DataFrame' object has no attribute 'column' 

Es scheint, dass der Teil der Schleife df.column.str verursacht ein Problem ? Ich habe mit der Liste herumgewürfelt, mit Bracketing-Spalte (ich verstehe immer noch nicht, warum ich manchmal eine DataFrame-Spalte umklammere und manchmal ist es .column, aber das ist ein größeres Problem) und andere zufällige Dinge.

Wenn ich versuche @ BrenBarn Vorschlag

df.apply(lambda c: c.str[:-2]) 

Folgende Pops im Jupyter Notebook up:

SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame 

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy 
    if __name__ == '__main__': 

an der Datenrahmen Blick hat sich nichts wirklich geändert und wenn ich die Dokumentation richtig verstehen Methode erstellt eine Kopie des Dataframe mit den Bearbeitungen, aber das ist eine temporäre Kopie, die später rausgeworfen wird, so dass sich der eigentliche DataFrame nicht ändert.

+0

Sie sagen, es funktioniert auch nicht, wenn Sie 'df [Spalte]' tun? – BrenBarn

+2

'df.column' entspricht' df ['column'] ', nicht' df [column] '. Wenn also Spalte eine Variable ist, kann sie nicht so verwendet werden. – ayhan

+0

@BrenBarn, yep, es funktioniert nicht, wenn ich 'df [Spalte]', 'df ['Spalte']' verwende, denke ich, ist das was @ayhan sagt. Also gibt es eine Antwort? – vino88

Antwort

2

Wenn die Positionsetiketten sind immer nur ein Zeichen, ist die einfache Lösung dieses:

>>> df.apply(lambda c: c.str[:-2]) 
      name1   name2 
0  Marc Gasol Lebron James 
1  Pau Gasol Kevin Durant 
2 Dwight Howard Kyrie Irving 

Das str Attribut einer Serie können Sie String-Operationen zu tun, einschließlich Indizierung, so dass diese Ordnungen nur die letzten beiden Zeichen aus jedem Wert.

Wie für Ihre Frage zu df.column, ist dieses Problem allgemeiner als Pandas. Diese beiden Dinge sind nicht das gleiche:

# works 
obj.attr 

# doesn't work 
attrName = 'attr' 
obj.attrName 

Sie nicht die Punktnotation verwenden können, wenn Sie ein Attribut, dessen Name zugreifen möchten, in einer Variablen gespeichert. Im Allgemeinen können Sie stattdessen die Funktion getattr verwenden. Pandas bietet jedoch die Klammernnotation für den Zugriff auf eine Spalte, indem der Name als Zeichenfolge (anstelle einer Quellcode-ID) angegeben wird. So sind diese beiden äquivalent:

df.some_column 

columnName = "some_column" 
df[columnName] 

In Ihrem Beispiel das Ändern Ihrer Bezug auf df.column zu df[column] sollte dieses Problem beheben. Wie ich in einem Kommentar erwähnt habe, hat Ihr Code jedoch auch andere Probleme.Was die Lösung der Aufgabe betrifft, ist der String-Indexing-Ansatz, den ich zu Beginn meiner Antwort gezeigt habe, viel einfacher.

+0

Ahhh, danke! – vino88

+0

Vielen Dank für die Lösung, leider, wenn ich dies auf dem eigentlichen DataFrame versuche ändert es eigentlich nichts. Im Jupyter-Notizbuch erscheint ein rotes Kästchen und besagt, dass ein Wert versucht wird, auf eine Kopie eines Segments von einem DataFrame gesetzt zu werden, und sagt, dass dies einen SettingWithCopy-Fehler auslöst. Die Dokumentation besagt, dass diese Methode eine Kopie einer temporären Ansicht des DataFrame zurückgeben kann, die später herausgeworfen wird, so dass sie nicht ausgeführt wird. – vino88

+1

@ vino88: Bearbeiten Sie dann Ihre Frage, um ein eigenständiges Beispiel mit dem Problem einzubinden. (Oder stellen Sie eine separate Frage, ob Ihre neue Frage wirklich diese neue Vorgehensweise betrifft und nicht mit dem Code zusammenhängt, den Sie hier gepostet haben.) – BrenBarn