1282 Stimmen

Wie füge ich eine neue Spalte zu einem vorhandenen DataFrame hinzu?

Ich habe das folgende indizierte DataFrame mit benannten Spalten und Zeilen, die nicht kontinuierliche Zahlen sind:

          a         b         c         d
2  0.671399  0.101208 -0.181532  0.241273
3  0.446172 -0.243316  0.051767  1.577318
5  0.614758  0.075793 -0.451460 -0.012493

Ich möchte eine neue Spalte, 'e', zum vorhandenen DataFrame hinzufügen und nichts im DataFrame ändern (d. h. die neue Spalte hat immer die gleiche Länge wie das DataFrame).

0   -0.335485
1   -1.166658
2   -0.385571
dtype: float64

Wie kann ich die Spalte e dem obigen Beispiel hinzufügen?

1289voto

joaquin Punkte 77782

Bearbeiten 2017

Wie in den Kommentaren und von @Alexander angegeben, könnte derzeit die beste Methode, um die Werte einer Serie als neue Spalte eines DataFrames hinzuzufügen, die Verwendung von assign sein:

df1 = df1.assign(e=pd.Series(np.random.randn(sLength)).values)

Bearbeiten 2015
Einige haben bei diesem Code die SettingWithCopyWarning gemeldet.
Jedoch läuft der Code immer noch perfekt mit der aktuellen pandas-Version 0.16.1.

>>> sLength = len(df1['a'])
>>> df1
          a         b         c         d
6 -0.269221 -0.026476  0.997517  1.294385
8  0.917438  0.847941  0.034235 -0.448948

>>> df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
          a         b         c         d         e
6 -0.269221 -0.026476  0.997517  1.294385  1.757167
8  0.917438  0.847941  0.034235 -0.448948  2.228131

>>> pd.version.short_version
'0.16.1'

Die SettingWithCopyWarning soll über eine möglicherweise ungültige Zuweisung an eine Kopie des Dataframes informieren. Es sagt nicht unbedingt, dass du etwas falsch gemacht hast (es kann zu falschen positiven Ergebnissen führen), aber ab 0.13.0 wird darauf hingewiesen, dass es bessere Methoden für denselben Zweck gibt. Wenn du also die Warnung erhältst, befolge einfach ihren Rat: Versuche stattdessen .loc[Zeilensindex,Spaltenindex] = Wert zu verwenden

>>> df1.loc[:,'f'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
          a         b         c         d         e         f
6 -0.269221 -0.026476  0.997517  1.294385  1.757167 -0.050927
8  0.917438  0.847941  0.034235 -0.448948  2.228131  0.006109
>>> 

Tatsächlich ist dies derzeit die effizientere Methode, wie in den Pandas-Dokumenten beschrieben


Ursprüngliche Antwort:

Verwenden Sie die originalen df1-Indizes, um die Serie zu erstellen:

df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)

314voto

Kathirmani Sukumar Punkte 9551

Dies ist die einfache Methode zum Hinzufügen einer neuen Spalte: df['e'] = e

213voto

Alexander Punkte 96032

Ich möchte eine neue Spalte 'e' zum vorhandenen Datenrahmen hinzufügen und nichts im Datenrahmen ändern. (Die Serie hat immer dieselbe Länge wie ein Datenrahmen.)

Ich gehe davon aus, dass die Indexwerte in e denen in df1 entsprechen.

Der einfachste Weg, eine neue Spalte mit dem Namen e zu initiieren und ihr die Werte aus Ihrer Serie e zuzuweisen:

df['e'] = e.values

assign (Pandas 0.16.0+)

Ab Pandas 0.16.0 können Sie auch assign verwenden, das neue Spalten einem Datenrahmen zuweist und ein neues Objekt (eine Kopie) mit allen originalen Spalten sowie den neuen zurückgibt.

df1 = df1.assign(e=e.values)

Wie in diesem Beispiel (das auch den Quellcode der assign-Funktion enthält) können Sie auch mehr als eine Spalte einschließen:

df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
>>> df.assign(mean_a=df.a.mean(), mean_b=df.b.mean())
   a  b  mean_a  mean_b
0  1  3     1.5     3.5
1  2  4     1.5     3.5

Im Zusammenhang mit Ihrem Beispiel:

np.random.seed(0)
df1 = pd.DataFrame(np.random.randn(10, 4), columns=['a', 'b', 'c', 'd'])
mask = df1.applymap(lambda x: x <-0.7)
df1 = df1[-mask.any(axis=1)]
sLength = len(df1['a'])
e = pd.Series(np.random.randn(sLength))

>>> df1
          a         b         c         d
0  1.764052  0.400157  0.978738  2.240893
2 -0.103219  0.410599  0.144044  1.454274
3  0.761038  0.121675  0.443863  0.333674
7  1.532779  1.469359  0.154947  0.378163
9  1.230291  1.202380 -0.387327 -0.302303

>>> e
0   -1.048553
1   -1.420018
2   -1.706270
3    1.950775
4   -0.509652
dtype: float64

df1 = df1.assign(e=e.values)

>>> df1
          a         b         c         d         e
0  1.764052  0.400157  0.978738  2.240893 -1.048553
2 -0.103219  0.410599  0.144044  1.454274 -1.420018
3  0.761038  0.121675  0.443863  0.333674 -1.706270
7  1.532779  1.469359  0.154947  0.378163  1.950775
9  1.230291  1.202380 -0.387327 -0.302303 -0.509652

Die Beschreibung dieses neuen Merkmals, als es zum ersten Mal eingeführt wurde, finden Sie hier.

75voto

firelynx Punkte 28306

Einfache Spaltenzuweisung

Ein Pandas-DataFrame ist als geordnetes Wörterbuch von Spalten implementiert.

Dies bedeutet, dass das __getitem__ [] nicht nur verwendet werden kann, um eine bestimmte Spalte abzurufen, sondern auch __setitem__ [] = verwendet werden kann, um eine neue Spalte zuzuweisen.

Zum Beispiel kann dieser DataFrame einfach eine Spalte hinzugefügt werden, indem der [] Accessor verwendet wird

    size      name color
0    big      rose   red
1  small    violet  blue
2  small     tulip   red
3  small  harebell  blue

df['protected'] = ['no', 'no', 'no', 'yes']

    size      name color protected
0    big      rose   red        no
1  small    violet  blue        no
2  small     tulip   red        no
3  small  harebell  blue       yes

Beachten Sie, dass dies auch funktioniert, wenn der Index des DataFrames nicht übereinstimmt.

df.index = [3,2,1,0]
df['protected'] = ['no', 'no', 'no', 'yes']
    size      name color protected
3    big      rose   red        no
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue       yes

[] = ist der Weg, aber Vorsicht!

Wenn Sie jedoch eine pd.Series haben und versuchen, sie einem DataFrame zuzuweisen, bei dem die Indizes nicht übereinstimmen, werden Sie auf Probleme stoßen. Sehen Sie das Beispiel:

df['protected'] = pd.Series(['no', 'no', 'no', 'yes'])
    size      name color protected
3    big      rose   red       yes
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue        no

Dies liegt daran, dass eine pd.Series standardmäßig einen Index hat, der von 0 bis n aufgezählt wird. Und die pandas [] = Methode versucht “intelligent” zu sein

Was tatsächlich passiert.

Wenn Sie die [] = Methode verwenden, führt Pandas stillschweigend ein Outer Join oder Outer Merge unter Verwendung des Index des linken DataFrames und des Index der rechten Serie durch. df['Spalte'] = Serie

Nebenbei bemerkt

Dies führt schnell zu kognitiver Dissonanz, da die [] = Methode je nach Eingabe viele verschiedene Dinge zu tun versucht und das Ergebnis nicht vorhergesagt werden kann, es sei denn, Sie wissen einfach, wie Pandas funktioniert. Ich würde daher von der Verwendung von [] = in Codebasen abraten, aber wenn Sie Daten in einem Notebook erkunden, ist es in Ordnung.

Umgehung des Problems

Wenn Sie eine pd.Series haben und sie von oben nach unten zuweisen möchten, oder wenn Sie produktiven Code schreiben und sich nicht sicher sind, in welcher Reihenfolge die Indizes stehen, lohnt es sich, sich gegen diese Art von Problem abzusichern.

Sie könnten die pd.Series in ein np.ndarray oder eine list umwandeln, das wird das Problem lösen.

df['protected'] = pd.Series(['no', 'no', 'no', 'yes']).values

oder

df['protected'] = list(pd.Series(['no', 'no', 'no', 'yes']))

Aber das ist nicht sehr explizit.

Einige Programmierer könnten kommen und sagen "Hey, das sieht redundant aus, ich werde das einfach optimieren".

Explizite Methode

Das Einstellen des Index der pd.Series auf den Index des df ist explizit.

df['protected'] = pd.Series(['no', 'no', 'no', 'yes'], index=df.index)

Oder realistischerweise haben Sie wahrscheinlich bereits eine pd.Series verfügbar.

protected_series = pd.Series(['no', 'no', 'no', 'yes'])
protected_series.index = df.index

3     no
2     no
1     no
0    yes

Kann nun zugewiesen werden

df['protected'] = protected_series

    size      name color protected
3    big      rose   red        no
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue       yes

Alternative Methode mit df.reset_index()

Da die Indexdifferenz das Problem ist, wenn Sie der Meinung sind, dass der Index des DataFrames nicht die Dinge diktiert, können Sie einfach den Index löschen, das sollte schneller sein, aber es ist nicht sehr sauber, da Ihre Funktion jetzt vermutlich zwei Dinge tut.

df.reset_index(drop=True)
protected_series.reset_index(drop=True)
df['protected'] = protected_series

    size      name color protected
0    big      rose   red        no
1  small    violet  blue        no
2  small     tulip   red        no
3  small  harebell  blue       yes

Hinweis zu df.assign

Obwohl df.assign deutlicher macht, was Sie tun, hat es tatsächlich alle Probleme wie das oben genannte [] =

df.assign(protected=pd.Series(['no', 'no', 'no', 'yes']))
    size      name color protected
3    big      rose   red       yes
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue        no

Achten Sie nur bei df.assign darauf, dass Ihre Spalte nicht self genannt wird. Es wird Fehler verursachen. Das macht df.assign schwierig, da es diese Art von Artefakten in der Funktion gibt.

df.assign(self=pd.Series(['no', 'no', 'no', 'yes'])
TypeError: assign() got multiple values for keyword argument 'self'

Sie könnten sagen: "Nun, ich werde einfach kein self verwenden". Aber wer weiß, wie sich diese Funktion in der Zukunft ändert, um neue Argumente zu unterstützen. Vielleicht wird Ihr Spaltenname in einem neuen Update von Pandas ein Argument sein, das beim Upgrade Probleme verursacht.

60voto

Mikhail Korobov Punkte 21059

Es scheint, dass in neueren Pandas-Versionen der Weg ist, df.assign zu verwenden:

df1 = df1.assign(e=np.random.randn(sLength))

Es erzeugt keine SettingWithCopyWarning.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X