2017-08-28 1 views
1

Betrachten Sie dieses einfache BeispielZugriff auf dynamische Erzeugen eines Pandas Datenrahmen Spalte

import pandas as pd 

df = pd.DataFrame({'one' : [1,2,3], 
        'two' : [1,0,0]}) 

df 
Out[9]: 
    one two 
0 1 1 
1 2 0 
2 3 0 

ich eine Funktion schreiben möchten, wie nimmt gibt einen Datenrahmen df und eine Spalte mycol.

Jetzt funktioniert das:

df.groupby('one').two.sum() 
Out[10]: 
one 
1 1 
2 0 
3 0 
Name: two, dtype: int64 

das funktioniert auch:

def okidoki(df,mycol): 
    return df.groupby('one')[mycol].sum() 

okidoki(df, 'two') 
Out[11]: 
one 
1 1 
2 0 
3 0 
Name: two, dtype: int64 

aber FAILS

def megabug(df,mycol): 
    return df.groupby('one').mycol.sum() 

megabug(df, 'two') 
AttributeError: 'DataFrameGroupBy' object has no attribute 'mycol' 

Was ist hier falsch?

Ich bin besorgt, dass okidoki verwendet einige verketten, die einige subtile Bugs schaffen könnten (https://pandas.pydata.org/pandas-docs/stable/indexing.html#why-does-assignment-fail-when-using-chained-indexing). Wie kann ich immer noch die Syntax groupby('one').mycol behalten? Kann der String in etwas umgewandelt werden, das auf diese Weise funktioniert? Danke!

Antwort

2

Sie übergeben eine Zeichenfolge als zweites Argument. In der Tat, Sie versuchen, etwas zu tun wie:

df.'two' 

Welche ungültige Syntax ist. Wenn Sie versuchen, dynamisch auf eine Spalte zuzugreifen, müssen Sie die Indexnotation [...] verwenden, da die dot/attribute Accessor-Notation nicht für dynamischen Zugriff verwendet werden kann.


Dynamischer Zugriff allein ist möglich.Zum Beispiel können Sie getattr verwenden (aber ich tun dies nicht empfehlen, es ist ein Antipattern):

In [674]: df 
Out[674]: 
    one two 
0 1 1 
1 2 0 
2 3 0 

In [675]: getattr(df, 'one') 
Out[675]: 
0 1 
1 2 
2 3 
Name: one, dtype: int64 

dynamisch durch Attribut aus einem groupby Aufruf der Auswahl durchgeführt werden kann, so etwas wie:

In [677]: getattr(df.groupby('one'), mycol).sum() 
Out[677]: 
one 
1 1 
2 0 
3 0 
Name: two, dtype: int64 

Aber nicht tun Sie es. Es ist ein schreckliches Anti-Muster und viel unlesbarer als df.groupby('one')[mycol].sum().

+0

danke kaltspeed. Ich habe meine Frage bearbeitet. Wenn ich eine Zeichenfolge als Eingabe verwende, ist es dann möglich, sie in etwas umzuwandeln, das mit dieser Syntax arbeitet? Sag 'notastring = magicfunction (mycol)' und dann 'df.notastring' –

+1

@ ℕℴℴḆḽḘ Bearbeitete meine Antwort noch einmal. Es ist möglich, aber es ist ein schreckliches Anti-Muster. Tu es nicht. –

2

Ich glaube, Sie [] für ausgewählte Spalte für Spalte Namen müssen, was allgemeine Lösung ist zum Auswählen von Spalten, weil Auswahl nach Attributen viele exceptions haben:

  • Sie diesen Zugriff nutzen können nur dann, wenn der Index Element eine gültige Python-Kennung, z s.1 ist nicht erlaubt. Hier finden Sie eine Erklärung der gültigen Bezeichner.
  • Das Attribut ist nicht verfügbar, wenn es mit einem vorhandenen Methodennamen kollidiert, z. s.min ist nicht erlaubt.
  • Ebenso ist das Attribut nicht verfügbar, wenn es mit einer der folgenden Listen in Konflikt steht: index, major_axis, minor_axis, items, labels.
  • In jedem dieser Fälle funktioniert die Standardindexierung immer noch, z. s ['1'], s ['min'] und s ['index'] greifen auf das entsprechende Element oder die entsprechende Spalte zu.
def megabug(df,mycol): 
    return df.groupby('one')[mycol].sum() 

print (megabug(df, 'two')) 

one 
1 1 
2 0 
3 0 
Name: two, dtype: int64 
+0

ja jezrael, das ist die Okidoki-Funktion oben eigentlich: D. Meine Frage ist warum es so ist? –

Verwandte Themen