Hinzufügen einer neuen Spalte zu einem vorhandenen DataFrame in Python-Pandas

979

Ich habe den folgenden indizierten DataFrame mit benannten Spalten und Zeilen, die keine fortlaufenden 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 dem vorhandenen Datenrahmen eine neue Spalte hinzufügen 'e'und möchte nichts im Datenrahmen ändern (dh die neue Spalte hat immer die gleiche Länge wie der Datenrahmen).

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

Wie kann ich edem obigen Beispiel eine Spalte hinzufügen ?

tomasz74
quelle

Antworten:

1043

Verwenden Sie die ursprünglichen df1-Indizes, um die Serie zu erstellen:

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

Edit 2015
Einige berichteten, dass sie das SettingWithCopyWarningmit diesem Code bekommen haben.
Der Code läuft jedoch 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

>>> p.version.short_version
'0.16.1'

Die SettingWithCopyWarningZiele einer möglicherweise ungültigen Zuordnung auf einer Kopie des Datenrahmen zu informieren. Es heißt nicht unbedingt, dass Sie es falsch gemacht haben (es kann falsch positive Ergebnisse auslösen), aber ab 0.13.0 werden Sie darüber informiert, dass es für denselben Zweck geeignetere Methoden gibt. Wenn Sie dann die Warnung erhalten, befolgen Sie einfach die Anweisungen : Verwenden Sie stattdessen .loc [row_index, col_indexer] = value

>>> 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 Pandas-Dokumenten beschrieben


2017 bearbeiten

Wie in den Kommentaren und von @Alexander angegeben, könnte die derzeit beste Methode zum Hinzufügen der Werte einer Serie als neue Spalte eines DataFrame Folgendes verwenden assign:

df1 = df1.assign(e=pd.Series(np.random.randn(sLength)).values)
Joaquin
quelle
24
Wenn Sie eine Spalte voranstellen müssen, verwenden Sie DataFrame.insert: df1.insert (0, 'A', Serie (np.random.randn (sLength), index = df1.index))
lowtech
29
Ab Pandas Version 0.12 glaube ich, dass diese Syntax nicht optimal ist und warnt:SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead
Zhubarb
6
Das Folgen von .loc als SettingWithCopy-Warnung führt irgendwie zu mehr Warnung: ... self.obj [item_labels [indexer [info_axis]]] = value
seongjoo
12
@toto_tico Sie können ein kwargsWörterbuch wie folgt entpacken :df1 = df1.assign(**{'e': p.Series(np.random.randn(sLength)).values})
TC Proctor
23
Anstatt "aktuell" zu sagen oder Jahre zu referenzieren, verweisen Sie bitte auf die Versionsnummern der Pandas, z. B. "zwischen 0,14-0,16 do X, in 0,17+ do Y ..."
smci
229

Dies ist die einfache Möglichkeit, eine neue Spalte hinzuzufügen: df['e'] = e

Kathirmani Sukumar
quelle
154
Trotz der hohen Stimmenzahl: Diese Antwort ist falsch . Beachten Sie, dass das OP einen Datenrahmen mit nicht kontinuierlichen Indizes hat und e( Series(np.random.randn(sLength))) eine indizierte Serie 0-n generiert. Wenn Sie dies df1 zuweisen, erhalten Sie einige NaN-Zellen.
Joaquin
32
Was @joaquin sagt, ist wahr, aber solange Sie dies berücksichtigen, ist dies eine sehr nützliche Abkürzung.
VedTopkar
2
@ Eric Leschinski: Ich bin mir nicht sicher, wie Sie diese Frage bearbeiten können. my_dataframe = pd.DataFrame(columns=('foo', 'bar')). Zurücksetzen Ihrer Bearbeitung
Kathirmani Sukumar
1
Es hilft nicht, denn wenn Sie mehrere Zeilen haben und die Zuweisung verwenden, werden alle Zeilen der neuen Spalte mit dem Wert (in Ihrem Fall e) zugewiesen, der normalerweise unerwünscht ist.
Paniz
156

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

Ich gehe davon aus, dass die Indexwerte in edenen in übereinstimmen df1.

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

df['e'] = e.values

zuweisen (Pandas 0.16.0+)

Ab Pandas 0.16.0 können Sie auch verwenden assign, um einem DataFrame neue Spalten zuzuweisen und ein neues Objekt (eine Kopie) mit allen ursprünglichen Spalten zusätzlich zu den neuen zurückzugeben.

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

Gemäß diesem Beispiel (das auch den Quellcode der assignFunktion 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 dieser neuen Funktion bei ihrer Einführung finden Sie hier .

Alexander
quelle
2
Gibt es einen Kommentar zur relativen Leistung der beiden Methoden, wenn man bedenkt, dass die erste Methode ( df['e'] = e.values) keine Kopie des Datenrahmens erstellt, während die zweite Option (using df.assign) dies tut? In Fällen, in denen viele neue Spalten nacheinander hinzugefügt werden und große Datenrahmen vorhanden sind, würde ich eine viel bessere Leistung der ersten Methode erwarten.
Jhin
2
@jhin Ja, eine direkte Zuweisung ist offensichtlich viel, wenn Sie an einem festen Datenrahmen arbeiten. Der Vorteil der Verwendung assignbesteht darin, dass Sie Ihre Vorgänge miteinander verketten.
Alexander
Dies scheint sicherlich eine gute Balance zwischen explizit und implizit zu sein. +1: D
Abe Hoffman
2
Zum Spaßdf.assign(**df.mean().add_prefix('mean_'))
piRSquared
1
@Owlright Aus der Frage geht hervor, dass das OP einfach die Datenrahmen verkettet und den Index ignoriert. In diesem Fall funktionieren die oben genannten Methoden. Wenn Sie den Index beibehalten möchten, verwenden Sie so etwas wie df_new = pd.concat([df1, df2], axis=1), wobei Sie dies ignore_index=Falsestandardmäßig beachten .
Alexander
51

Es scheint, dass in neueren Pandas-Versionen df.assign verwendet werden muss :

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

Es produziert nicht SettingWithCopyWarning.

Mikhail Korobov
quelle
1
Kopieren von @smcis Kommentar von oben ... Anstatt "aktuell" zu sagen oder auf Jahre zu verweisen, verweisen Sie bitte auf die Pandas-Versionsnummern
Kyle C
50

Dies direkt über NumPy zu tun, ist am effizientesten:

df1['e'] = np.random.randn(sLength)

Beachten Sie, dass mein ursprünglicher (sehr alter) Vorschlag lautete map(was viel langsamer ist):

df1['e'] = df1['a'].map(lambda x: np.random.random())
Andy Hayden
quelle
1
Vielen Dank für Ihre Antwort, wie ich bereits gegeben habe. Kann ich Ihren Code ändern, .mapum vorhandene Serien anstelle von zu verwenden lambda? Ich versuche df1['e'] = df1['a'].map(lambda x: e)oder df1['e'] = df1['a'].map(e)aber es ist nicht was ich brauche. (Ich bin neu in Pyhon und Ihre vorherige Antwort hat mir bereits geholfen)
tomasz74
@ tomasz74 Wenn Sie bereits eals Serie haben, müssen Sie nicht verwenden map, verwenden Sie df['e']=e(@joaquins Antwort).
Andy Hayden
49

Super einfache Spaltenzuordnung

Ein Pandas-Datenrahmen wird als geordnetes Diktat von Spalten implementiert.

Dies bedeutet, dass mit dem __getitem__ []nicht nur eine bestimmte Spalte abgerufen werden __setitem__ [] =kann , sondern auch eine neue Spalte zugewiesen werden kann.

Beispielsweise kann diesem Datenrahmen eine Spalte hinzugefügt werden, indem einfach 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 dann funktioniert, wenn der Index des Datenrahmens deaktiviert ist.

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 richtige Weg, aber aufgepasst!

Wenn Sie jedoch einen haben pd.Seriesund versuchen, ihn einem Datenrahmen zuzuweisen, in dem die Indizes deaktiviert sind, treten Probleme auf. Siehe 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 a pd.Seriesstandardmäßig einen Index von 0 bis n hat. Und die Pandas- [] =Methode versucht , "klug" zu sein.

Was ist eigentlich los?

Wenn Sie die [] =Methode verwenden, führt pandas stillschweigend eine äußere Verknüpfung oder eine äußere Zusammenführung unter Verwendung des Index des linken Datenrahmens und des Index der rechten Reihe durch.df['column'] = series

Randnotiz

Dies führt schnell zu kognitiven Dissonanzen, da die []=Methode versucht, abhängig von der Eingabe viele verschiedene Dinge zu tun, und das Ergebnis nur vorhergesagt werden kann, wenn Sie nur wissen, wie Pandas funktionieren. Ich würde daher von den []=In-Code-Basen abraten, aber wenn Sie Daten in einem Notizbuch untersuchen, ist dies in Ordnung.

Das Problem umgehen

Wenn Sie eine haben pd.Seriesund möchten, dass sie von oben nach unten zugewiesen wird, oder wenn Sie produktiven Code codieren und sich der Indexreihenfolge nicht sicher sind, lohnt es sich, diese Art von Problem zu schützen.

Sie könnten das pd.Seriesauf a np.ndarrayoder a herabstürzen list, dies wird den Trick tun.

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

oder

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

Dies ist jedoch nicht sehr explizit.

Ein Programmierer könnte mitkommen und sagen: "Hey, das sieht überflüssig aus, ich optimiere das einfach weg."

Expliziter Weg

Das Festlegen des Index von pd.Seriesals Index von dfist explizit.

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

Oder realistischer, Sie haben wahrscheinlich bereits eine pd.Series.

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

3     no
2     no
1     no
0    yes

Kann jetzt 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

Alternativer Weg mit df.reset_index()

Da die Indexdissonanz das Problem ist, können Sie den Index einfach löschen, wenn Sie der Meinung sind, dass der Index des Datenrahmens keine Vorgaben machen sollte. Dies sollte schneller sein, ist aber nicht sehr sauber, da Ihre Funktion jetzt wahrscheinlich 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

Während df.assignmachen es noch deutlicher , was Sie tun, es hat eigentlich alle dieselben Probleme wie die oben[]=

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

Pass nur auf, df.assigndass deine Kolumne nicht aufgerufen wird self. Es wird Fehler verursachen. Dies macht df.assign stinkend , 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önnen sagen: "Nun, ich werde dann einfach nicht verwenden self". Aber wer weiß, wie sich diese Funktion in Zukunft ändert, um neue Argumente zu unterstützen. Möglicherweise ist Ihr Spaltenname ein Argument in einem neuen Update von Pandas, das Probleme beim Upgrade verursacht.

Firelynx
quelle
6
" Wenn Sie die [] =Methode verwenden, führt pandas leise einen äußeren Join oder eine äußere Zusammenführung durch. " Dies ist die wichtigste Information im gesamten Thema. Aber können Sie einen Link zur offiziellen Dokumentation zur Funktionsweise des []=Betreibers bereitstellen ?
Lightman
25

Einfachste Möglichkeiten: -

data['new_col'] = list_of_values

data.loc[ : , 'new_col'] = list_of_values

Auf diese Weise vermeiden Sie die sogenannte verkettete Indizierung, wenn Sie neue Werte in einem Pandas-Objekt festlegen. Klicken Sie hier, um weiterzulesen .

Abhishek
quelle
23

Wenn Sie die gesamte neue Spalte auf einen anfänglichen Basiswert setzen möchten (z. B. None), können Sie dies tun:df1['e'] = None

Dies würde der Zelle tatsächlich den Typ "Objekt" zuweisen. So können Sie später komplexe Datentypen wie Listen in einzelne Zellen einfügen.

digdug
quelle
1
Dies löst eine Einstellung mit Kopierwarnung
00__00__00
1
df ['E'] = '' funktioniert auch, wenn jemand eine leere Spalte hinzufügen möchte
debaonline4u
21

Ich habe das gefürchtet SettingWithCopyWarningund es wurde nicht mit der iloc-Syntax behoben. Mein DataFrame wurde von read_sql aus einer ODBC-Quelle erstellt. Mit einem Vorschlag von Lowtech oben hat Folgendes für mich funktioniert:

df.insert(len(df.columns), 'e', pd.Series(np.random.randn(sLength),  index=df.index))

Dies funktionierte gut, um die Spalte am Ende einzufügen. Ich weiß nicht, ob es am effizientesten ist, aber ich mag keine Warnmeldungen. Ich denke, es gibt eine bessere Lösung, aber ich kann sie nicht finden, und ich denke, es hängt von einem Aspekt des Index ab.
Hinweis . Dass dies nur einmal funktioniert und eine Fehlermeldung ausgibt, wenn versucht wird, eine vorhandene Spalte zu überschreiben.
Hinweis Wie oben und ab 0.16.0 ist die Zuweisung die beste Lösung. Siehe Dokumentation http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign Funktioniert gut für Datenflusstypen, bei denen Sie Ihre Zwischenwerte nicht überschreiben.

hum3
quelle
Dies ist der einzige Weg, der 2019 für mich funktioniert!
Hydradon
14
  1. Erstellen Sie zuerst eine Python list_of_emit relevanten Daten.
  2. Benutze das: df['e'] = list_of_e
Sumit Pokhrel
quelle
1
Ich verstehe wirklich nicht, warum dies nicht die bevorzugte Antwort ist. Wenn Sie eine pd.Series haben, kann der tolist()Befehl hilfreich sein.
Also S
11

Wenn die Spalte, die Sie hinzufügen möchten, eine Serienvariable ist, dann nur:

df["new_columns_name"]=series_variable_name #this will do it for you

Dies funktioniert auch dann gut, wenn Sie eine vorhandene Spalte ersetzen. Geben Sie einfach den Namen new_columns_name ein, der der Spalte entspricht, die Sie ersetzen möchten. Die vorhandenen Spaltendaten werden nur mit den neuen Seriendaten überschrieben.

Akshay Singhvi
quelle
10

Wenn der Datenrahmen und das Serienobjekt denselben Index haben , pandas.concatfunktioniert dies auch hier:

import pandas as pd
df
#          a            b           c           d
#0  0.671399     0.101208   -0.181532    0.241273
#1  0.446172    -0.243316    0.051767    1.577318
#2  0.614758     0.075793   -0.451460   -0.012493

e = pd.Series([-0.335485, -1.166658, -0.385571])    
e
#0   -0.335485
#1   -1.166658
#2   -0.385571
#dtype: float64

# here we need to give the series object a name which converts to the new  column name 
# in the result
df = pd.concat([df, e.rename("e")], axis=1)
df

#          a            b           c           d           e
#0  0.671399     0.101208   -0.181532    0.241273   -0.335485
#1  0.446172    -0.243316    0.051767    1.577318   -1.166658
#2  0.614758     0.075793   -0.451460   -0.012493   -0.385571

Falls sie nicht den gleichen Index haben:

e.index = df.index
df = pd.concat([df, e.rename("e")], axis=1)
Psidom
quelle
10

Narrensicher:

df.loc[:, 'NewCol'] = 'New_Val'

Beispiel:

df = pd.DataFrame(data=np.random.randn(20, 4), columns=['A', 'B', 'C', 'D'])

df

           A         B         C         D
0  -0.761269  0.477348  1.170614  0.752714
1   1.217250 -0.930860 -0.769324 -0.408642
2  -0.619679 -1.227659 -0.259135  1.700294
3  -0.147354  0.778707  0.479145  2.284143
4  -0.529529  0.000571  0.913779  1.395894
5   2.592400  0.637253  1.441096 -0.631468
6   0.757178  0.240012 -0.553820  1.177202
7  -0.986128 -1.313843  0.788589 -0.707836
8   0.606985 -2.232903 -1.358107 -2.855494
9  -0.692013  0.671866  1.179466 -1.180351
10 -1.093707 -0.530600  0.182926 -1.296494
11 -0.143273 -0.503199 -1.328728  0.610552
12 -0.923110 -1.365890 -1.366202 -1.185999
13 -2.026832  0.273593 -0.440426 -0.627423
14 -0.054503 -0.788866 -0.228088 -0.404783
15  0.955298 -1.430019  1.434071 -0.088215
16 -0.227946  0.047462  0.373573 -0.111675
17  1.627912  0.043611  1.743403 -0.012714
18  0.693458  0.144327  0.329500 -0.655045
19  0.104425  0.037412  0.450598 -0.923387


df.drop([3, 5, 8, 10, 18], inplace=True)

df

           A         B         C         D
0  -0.761269  0.477348  1.170614  0.752714
1   1.217250 -0.930860 -0.769324 -0.408642
2  -0.619679 -1.227659 -0.259135  1.700294
4  -0.529529  0.000571  0.913779  1.395894
6   0.757178  0.240012 -0.553820  1.177202
7  -0.986128 -1.313843  0.788589 -0.707836
9  -0.692013  0.671866  1.179466 -1.180351
11 -0.143273 -0.503199 -1.328728  0.610552
12 -0.923110 -1.365890 -1.366202 -1.185999
13 -2.026832  0.273593 -0.440426 -0.627423
14 -0.054503 -0.788866 -0.228088 -0.404783
15  0.955298 -1.430019  1.434071 -0.088215
16 -0.227946  0.047462  0.373573 -0.111675
17  1.627912  0.043611  1.743403 -0.012714
19  0.104425  0.037412  0.450598 -0.923387

df.loc[:, 'NewCol'] = 0

df
           A         B         C         D  NewCol
0  -0.761269  0.477348  1.170614  0.752714       0
1   1.217250 -0.930860 -0.769324 -0.408642       0
2  -0.619679 -1.227659 -0.259135  1.700294       0
4  -0.529529  0.000571  0.913779  1.395894       0
6   0.757178  0.240012 -0.553820  1.177202       0
7  -0.986128 -1.313843  0.788589 -0.707836       0
9  -0.692013  0.671866  1.179466 -1.180351       0
11 -0.143273 -0.503199 -1.328728  0.610552       0
12 -0.923110 -1.365890 -1.366202 -1.185999       0
13 -2.026832  0.273593 -0.440426 -0.627423       0
14 -0.054503 -0.788866 -0.228088 -0.404783       0
15  0.955298 -1.430019  1.434071 -0.088215       0
16 -0.227946  0.047462  0.373573 -0.111675       0
17  1.627912  0.043611  1.743403 -0.012714       0
19  0.104425  0.037412  0.450598 -0.923387       0
K88
quelle
2
Nicht kinderleicht. Dies geht nicht auf die Frage des OP ein. In diesem Fall sind die Indizes des vorhandenen Datenrahmens und der neuen Reihe nicht aufeinander abgestimmt.
Alexander
7

Lassen Sie mich nur hinzufügen, dass, genau wie bei hum3 , .locdas nicht gelöst wurde SettingWithCopyWarningund ich darauf zurückgreifen musste df.insert(). In meinem Fall wurde durch "gefälschte" Kettenindizierung ein falsches Positiv generiert. dict['a']['e']Dabei 'e'handelt es sich um die neue Spalte und dict['a']einen aus dem Wörterbuch stammenden DataFrame.

Beachten Sie auch, dass Sie, wenn Sie wissen, was Sie tun, die Warnung mit pd.options.mode.chained_assignment = None einer der anderen hier angegebenen Lösungen ausschalten und dann verwenden können.

kkumer
quelle
7

Verwenden Sie einfach Dataframe.insert, um eine neue Spalte an einer bestimmten Stelle (0 <= loc <= Anzahl der Spalten) in einen Datenrahmen einzufügen:

DataFrame.insert(loc, column, value)

Wenn Sie also die Spalte e am Ende eines Datenrahmens mit dem Namen df hinzufügen möchten , können Sie Folgendes verwenden:

e = [-0.335485, -1.166658, -0.385571]    
DataFrame.insert(loc=len(df.columns), column='e', value=e)

Der Wert kann eine Reihe, eine Ganzzahl (in diesem Fall werden alle Zellen mit diesem einen Wert gefüllt) oder eine Array-ähnliche Struktur sein

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.insert.html

Nooyi
quelle
6

Wenn Sie vor dem Zuweisen einer neuen Spalte Daten indiziert haben, müssen Sie den Index sortieren. Zumindest in meinem Fall musste ich:

data.set_index(['index_column'], inplace=True)
"if index is unsorted, assignment of a new column will fail"        
data.sort_index(inplace = True)
data.loc['index_value1', 'column_y'] = np.random.randn(data.loc['index_value1', 'column_x'].shape[0])
Dima Lituiev
quelle
6

Eine Sache zu beachten ist jedoch, dass, wenn Sie dies tun

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

Dies wird effektiv ein linker Join im df1.index sein. Wenn Sie also einen äußeren Verknüpfungseffekt erzielen möchten , besteht meine wahrscheinlich unvollständige Lösung darin, einen Datenrahmen mit Indexwerten zu erstellen, die das Universum Ihrer Daten abdecken, und dann den obigen Code zu verwenden. Zum Beispiel,

data = pd.DataFrame(index=all_possible_values)
df1['e'] = Series(np.random.randn(sLength), index=df1.index)
WillZ
quelle
5

Ich suchte nach einer allgemeinen Möglichkeit numpy.nan, einem Datenrahmen eine Spalte mit s hinzuzufügen, ohne dumm zu werden SettingWithCopyWarning.

Aus dem Folgenden:

  • die Antworten hier
  • Diese Frage zum Übergeben einer Variablen als Schlüsselwortargument
  • Diese Methode zum Erzeugen eines numpyArrays von NaNs inline

Ich habe mir das ausgedacht:

col = 'column_name'
df = df.assign(**{col:numpy.full(len(df), numpy.nan)})
Ryanjdillon
quelle
4

So fügen Sie dem vorhandenen Datenrahmen eine neue Spalte "e" hinzu

 df1.loc[:,'e'] = Series(np.random.randn(sLength))
Chirag
quelle
Es gibt auch die Einschränkung Nachricht
B Furtado
Sie sollten df1.loc [::, 'e'] = Series (np.random.randn (sLength)) verwenden
Hermes Morales
4

Der Vollständigkeit halber - eine weitere Lösung mit der DataFrame.eval () -Methode:

Daten:

In [44]: e
Out[44]:
0    1.225506
1   -1.033944
2   -0.498953
3   -0.373332
4    0.615030
5   -0.622436
dtype: float64

In [45]: df1
Out[45]:
          a         b         c         d
0 -0.634222 -0.103264  0.745069  0.801288
4  0.782387 -0.090279  0.757662 -0.602408
5 -0.117456  2.124496  1.057301  0.765466
7  0.767532  0.104304 -0.586850  1.051297
8 -0.103272  0.958334  1.163092  1.182315
9 -0.616254  0.296678 -0.112027  0.679112

Lösung:

In [46]: df1.eval("e = @e.values", inplace=True)

In [47]: df1
Out[47]:
          a         b         c         d         e
0 -0.634222 -0.103264  0.745069  0.801288  1.225506
4  0.782387 -0.090279  0.757662 -0.602408 -1.033944
5 -0.117456  2.124496  1.057301  0.765466 -0.498953
7  0.767532  0.104304 -0.586850  1.051297 -0.373332
8 -0.103272  0.958334  1.163092  1.182315  0.615030
9 -0.616254  0.296678 -0.112027  0.679112 -0.622436
MaxU
quelle
4

So erstellen Sie eine leere Spalte

df['i'] = None
JNZ
quelle
3

Folgendes habe ich getan ... Aber ich bin ziemlich neu in Pandas und wirklich Python im Allgemeinen, also keine Versprechen.

df = pd.DataFrame([[1, 2], [3, 4], [5,6]], columns=list('AB'))

newCol = [3,5,7]
newName = 'C'

values = np.insert(df.values,df.shape[1],newCol,axis=1)
header = df.columns.values.tolist()
header.append(newName)

df = pd.DataFrame(values,columns=header)
Devin Charles
quelle
3

Wenn Sie das erhalten SettingWithCopyWarning, besteht eine einfache Lösung darin, den DataFrame zu kopieren, dem Sie eine Spalte hinzufügen möchten.

df = df.copy()
df['col_name'] = values
Fredcallaway
quelle
10
Das ist keine gute Idee. Wenn der Datenrahmen groß genug ist, wird er speicherintensiv ... Außerdem würde es zu einem Albtraum werden, wenn Sie ab und zu Spalten hinzufügen.
Kevad