2016-04-06 5 views
2

Ich habe über diese zu lesen und immer noch das Thema ein wenig verwirrend finden: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copySet erste und die letzte Zeile einer Spalte in einem Datenrahmen

sagen, dass ich ein Panda-Datenrahmen haben und ich möchte die erste gleichzeitig eingestellt und letzte Zeilenelemente einer einzelnen Spalte auf einen beliebigen Wert. Ich kann dies tun:

df.iloc[[0, -1]].mycol = [1, 2]

, die sagt mir A value is trying to be set on a copy of a slice from a DataFrame. und dass dies potentiell gefährlich.

Ich könnte stattdessen .loc verwenden, aber dann muss ich den Index der ersten und letzten Zeilen wissen (im Gegensatz, .iloc ermöglicht mir den Zugriff nach Standort).

Was ist der sicherste Pandasy-Weg, dies zu tun?

zu diesem Punkt zu kommen:

# Django queryset 
query = market.stats_set.annotate(distance=F("end_date") - query_date) 

# Generate a dataframe from this queryset, and order by distance 
df = pd.DataFrame.from_records(query.values("distance", *fields), coerce_float=True) 
df = df.sort_values("distance").reset_index(drop=True) 

Dann versuche ich, ruft df.distance.iloc[[0, -1]] = [1, 2]. Dies wirft die Warnung auf.

+1

funktioniert 'df ['mycol']. Iloc [[0, -1]] = [1, 2]' Arbeit? – EdChum

+0

Gleiche Warnung, ob ich Zeilen oder Spalten zuerst indexiere. – Quentin

+0

Sie müssen genau alle Schritte zeigen, die zu der Warnung führen, da meine Antwort zeigt, dass dies richtig funktioniert – EdChum

Antwort

2

Das Problem ist nicht mit iloc, es ist, wenn Sie auf zugreifen, dass eine Kopie erstellt wird. Sie können dies alles innerhalb iloc:

df.iloc[[0, -1], df.columns.get_loc('mycol')] = [1, 2] 

Normalerweise ix verwendet wird, wenn Sie Misch integer und Label aus zugreifen möchten, aber in diesem Fall nicht funktioniert, da -1 eigentlich nicht in den Index ist, und anscheinend ix ist nicht schlau genug zu wissen, dass es der letzte Index sein sollte.

+0

Ah! Dort wird die Kopie erstellt. Vielen Dank ! – Quentin

1

Was Sie tun gekettet Indizierung genannt wird, können Sie iloc auf dieser Spalte verwenden nur die Warnung zu vermeiden:

In [24]: 
df = pd.DataFrame(np.random.randn(5,3), columns=list('abc')) 

Out[24]: 
      a   b   c 
0 1.589940 0.735713 -1.158907 
1 0.485653 0.044611 0.070907 
2 1.123221 -0.862393 -0.807051 
3 0.338653 -0.734169 -0.070471 
4 0.344794 1.095861 -1.300339 

In [25]: 
df['a'].iloc[[0,-1]] ='foo' 
df 

Out[25]: 
      a   b   c 
0  foo 0.735713 -1.158907 
1 0.485653 0.044611 0.070907 
2 1.12322 -0.862393 -0.807051 
3 0.338653 -0.734169 -0.070471 
4  foo 1.095861 -1.300339 

Wenn Sie es anders zu tun, dann stellt sich die Warnung:

In [27]: 
df.iloc[[0,-1]]['a'] ='foo' 

C:\WinPython-64bit-3.4.3.1\python-3.4.3.amd64\lib\site-packages\IPython\kernel\__main__.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame. 
Try using .loc[row_indexer,col_indexer] = value instead 

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

Eigentlich macht 'df.mycol.iloc [[0, -1]]' noch immer eine Warnung für mich. Ich bin auf 0.17.1. Ich frage mich, ob es daran liegt, dass es mit 'pd.DataFrame.from_records' erstellt wurde, denn wenn ich deins starte, gibt es keine Warnung. – Quentin

+0

Ich hatte das gleiche Problem auf 0.18.0. Wenn ich den obigen Code ausgeführt habe, habe ich die Warnung nicht erhalten, aber die Warnung wurde ausgelöst, wenn ich die gleiche Methode für einige Testdaten verwendete, die ich erstellt habe. Seltsam. – root

+0

Gelegentlich wünschst du dir, dass Python den Begriff der Zeiger expliziter macht;) – Quentin

Verwandte Themen