Wie füge ich dem Pandas-Datenrahmen in einer Zuweisung mehrere Spalten hinzu?

120

Ich bin neu in Pandas und versuche herauszufinden, wie man Pandas mehrere Spalten gleichzeitig hinzufügt. Jede Hilfe hier wird geschätzt. Idealerweise möchte ich dies in einem Schritt tun und nicht in mehreren wiederholten Schritten ...

import pandas as pd

df = {'col_1': [0, 1, 2, 3],
        'col_2': [4, 5, 6, 7]}
df = pd.DataFrame(df)

df[[ 'column_new_1', 'column_new_2','column_new_3']] = [np.nan, 'dogs',3]  #thought this would work here...
Runningbirds
quelle
Sie müssen angeben, welchen Fehler Sie erhalten haben. Wenn ich das auf Pandas 1.0 versuche, bekomme ichKeyError: "None of [Index(['column_new_1', 'column_new_2', 'column_new_3'], dtype='object')] are in the [columns]"
smci

Antworten:

182

Ich hätte erwartet, dass Ihre Syntax auch funktioniert. Das Problem tritt auf, weil df[[new1, new2]] = ...Pandas beim Erstellen neuer Spalten mit der Spaltenlistensyntax ( ) erfordert, dass die rechte Seite ein DataFrame ist (beachten Sie, dass es eigentlich keine Rolle spielt, ob die Spalten des DataFrame dieselben Namen wie die Spalten haben Sie erstellen).

Ihre Syntax eignet sich gut zum Zuweisen von Skalarwerten zu vorhandenen Spalten, und Pandas vergibt auch gerne Skalarwerte zu einer neuen Spalte mithilfe der einspaltigen Syntax ( df[new1] = ...). Die Lösung besteht also entweder darin, dies in mehrere einspaltige Zuweisungen zu konvertieren oder einen geeigneten DataFrame für die rechte Seite zu erstellen.

Hier sind einige Ansätze, die funktionieren werden:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'col_1': [0, 1, 2, 3],
    'col_2': [4, 5, 6, 7]
})

Dann eine der folgenden:

1) Drei Aufgaben in einer, wobei die Liste entpackt wird:

df['column_new_1'], df['column_new_2'], df['column_new_3'] = [np.nan, 'dogs', 3]

2) DataFrameErweitert bequemerweise eine einzelne Zeile, um sie an den Index anzupassen. So können Sie Folgendes tun:

df[['column_new_1', 'column_new_2', 'column_new_3']] = pd.DataFrame([[np.nan, 'dogs', 3]], index=df.index)

3) Erstellen Sie einen temporären Datenrahmen mit neuen Spalten und kombinieren Sie ihn später mit dem ursprünglichen Datenrahmen:

df = pd.concat(
    [
        df,
        pd.DataFrame(
            [[np.nan, 'dogs', 3]], 
            index=df.index, 
            columns=['column_new_1', 'column_new_2', 'column_new_3']
        )
    ], axis=1
)

4) Ähnlich wie beim vorherigen, jedoch joinanstelle von concat(möglicherweise weniger effizient):

df = df.join(pd.DataFrame(
    [[np.nan, 'dogs', 3]], 
    index=df.index, 
    columns=['column_new_1', 'column_new_2', 'column_new_3']
))

5) Die Verwendung eines Diktats ist eine "natürlichere" Methode zum Erstellen des neuen Datenrahmens als die beiden vorherigen, aber die neuen Spalten werden alphabetisch sortiert (zumindest vor Python 3.6 oder 3.7 ):

df = df.join(pd.DataFrame(
    {
        'column_new_1': np.nan,
        'column_new_2': 'dogs',
        'column_new_3': 3
    }, index=df.index
))

6) Verwendung .assign()mit mehreren Spaltenargumenten.

Ich mag diese Variante der Antwort von @ zero sehr, aber wie die vorherige werden die neuen Spalten immer alphabetisch sortiert, zumindest bei früheren Versionen von Python:

df = df.assign(column_new_1=np.nan, column_new_2='dogs', column_new_3=3)

7) Das ist interessant (basierend auf https://stackoverflow.com/a/44951376/3830997 ), aber ich weiß nicht, wann es die Mühe wert wäre:

new_cols = ['column_new_1', 'column_new_2', 'column_new_3']
new_vals = [np.nan, 'dogs', 3]
df = df.reindex(columns=df.columns.tolist() + new_cols)   # add empty cols
df[new_cols] = new_vals  # multi-column assignment works for existing cols

8) Am Ende ist es schwer, drei separate Aufgaben zu meistern:

df['column_new_1'] = np.nan
df['column_new_2'] = 'dogs'
df['column_new_3'] = 3

Hinweis: Viele dieser Optionen wurden bereits in anderen Antworten behandelt: Fügen Sie DataFrame mehrere Spalten hinzu und setzen Sie sie auf eine vorhandene Spalte . Ist es möglich, einem Pandas DataFrame mehrere Spalten gleichzeitig hinzuzufügen? , Fügen Sie Pandas DataFrame mehrere leere Spalten hinzu

Matthias Fripp
quelle
Würde Ansatz # 7 ( .reindex) den Index des Datenrahmens nicht ändern? Warum sollte jemand den Index beim Hinzufügen von Spalten unnötig ändern wollen, es sei denn, dies ist ein explizites Ziel ...
Acumenus
1
.reindex()wird mit dem columnsArgument verwendet, so dass nur die Spalte "Index" (Namen) geändert wird. Der Zeilenindex wird nicht geändert.
Matthias Fripp
Für einige der Ansätze können Sie OrderedDictdf.join(pd.DataFrame( OrderedDict([('column_new_2', 'dogs'),('column_new_1', np.nan),('column_new_3', 3)]), index=df.index ))
Folgendes
@hashmuke Das macht Sinn für frühe Versionen von Python. Es kann besonders Menschen ansprechen, die Wörterbücher für verschiedene Dinge in Pandas verwenden, z. B. df = pd.DataFrame({'before': [1, 2, 3], 'after': [4, 5, 6]})vs.df = pd.DataFrame(OrderedDict([('before', [1, 2, 3]), ('after', [4, 5, 6])])
Matthias Fripp
2
Wenn Sie die Option mit verwenden join, stellen Sie sicher, dass Ihr Index keine Duplikate enthält (oder verwenden Sie eine reset_indexerste). Könnte Ihnen ein paar Stunden beim Debuggen ersparen.
Guido
40

Sie können assignmit einem Diktat von Spaltennamen und Werten verwenden.

In [1069]: df.assign(**{'col_new_1': np.nan, 'col2_new_2': 'dogs', 'col3_new_3': 3})
Out[1069]:
   col_1  col_2 col2_new_2  col3_new_3  col_new_1
0      0      4       dogs           3        NaN
1      1      5       dogs           3        NaN
2      2      6       dogs           3        NaN
3      3      7       dogs           3        NaN
Null
quelle
Gibt es eine Möglichkeit, dasselbe zu tun, bei der eine bestimmte Reihenfolge der Spalten beibehalten wird?
user48956
1
Sie können eine bestimmte Reihenfolge mit früheren Versionen von Python beibehalten, indem Sie die Zuweisung mehrmals aufrufen: df.assign(**{'col_new_1': np.nan}).assign(**{'col2_new_2': 'dogs'}).assign(**{'col3_new_3': 3})
skasch
9

Mit der Verwendung von concat :

In [128]: df
Out[128]: 
   col_1  col_2
0      0      4
1      1      5
2      2      6
3      3      7

In [129]: pd.concat([df, pd.DataFrame(columns = [ 'column_new_1', 'column_new_2','column_new_3'])])
Out[129]: 
   col_1  col_2 column_new_1 column_new_2 column_new_3
0    0.0    4.0          NaN          NaN          NaN
1    1.0    5.0          NaN          NaN          NaN
2    2.0    6.0          NaN          NaN          NaN
3    3.0    7.0          NaN          NaN          NaN

Ich bin mir nicht sicher, womit du machen wolltest [np.nan, 'dogs',3]. Vielleicht setzen Sie sie jetzt als Standardwerte?

In [142]: df1 = pd.concat([df, pd.DataFrame(columns = [ 'column_new_1', 'column_new_2','column_new_3'])])
In [143]: df1[[ 'column_new_1', 'column_new_2','column_new_3']] = [np.nan, 'dogs', 3]

In [144]: df1
Out[144]: 
   col_1  col_2  column_new_1 column_new_2  column_new_3
0    0.0    4.0           NaN         dogs             3
1    1.0    5.0           NaN         dogs             3
2    2.0    6.0           NaN         dogs             3
3    3.0    7.0           NaN         dogs             3
Nehal J Wani
quelle
Wenn es eine Möglichkeit gab, Ihren zweiten Teil in einem Schritt zu erledigen - ja, konstante Werte in den Spalten als Beispiel.
Runningbirds
3

Verwendung des Listenverständnisses pd.DataFrameundpd.concat

pd.concat(
    [
        df,
        pd.DataFrame(
            [[np.nan, 'dogs', 3] for _ in range(df.shape[0])],
            df.index, ['column_new_1', 'column_new_2','column_new_3']
        )
    ], axis=1)

Geben Sie hier die Bildbeschreibung ein

piRSquared
quelle
3

Wenn ich viele fehlende Spalten (a, b, c, ....) mit demselben Wert hinzufüge, hier 0, habe ich Folgendes getan:

    new_cols = ["a", "b", "c" ] 
    df[new_cols] = pd.DataFrame([[0] * len(new_cols)], index=df.index)

Es basiert auf der zweiten Variante der akzeptierten Antwort.

A. Rabus
quelle
0

Ich möchte nur auf diese Option2 in der Antwort von @Matthias Fripp hinweisen

(2) Ich würde nicht unbedingt erwarten, dass DataFrame so funktioniert, aber es funktioniert

df [['column_new_1', 'column_new_2', 'column_new_3']] = pd.DataFrame ([[np.nan, 'Hunde', 3]], index = df.index)

ist bereits in der eigenen Dokumentation von pandas http://pandas.pydata.org/pandas-docs/stable/indexing.html#basics dokumentiert

Sie können eine Liste von Spalten an [] übergeben, um Spalten in dieser Reihenfolge auszuwählen. Wenn der DataFrame keine Spalte enthält, wird eine Ausnahme ausgelöst. Auf diese Weise können auch mehrere Spalten festgelegt werden. Dies kann nützlich sein, um eine Transformation ( direkt ) auf eine Teilmenge der Spalten anzuwenden .

halbmond halb
quelle
Ich denke, das ist ziemlich Standard für mehrspaltige Zuweisungen. Der Teil, der mich überrascht hat, war, dass er pd.DataFrame([[np.nan, 'dogs', 3]], index=df.index)die eine Zeile repliziert, die ihm gegeben wurde, um einen ganzen Datenrahmen mit der gleichen Länge wie der Index zu erstellen.
Matthias Fripp
0

Wenn Sie nur leere neue Spalten hinzufügen möchten, erledigt die Neuindizierung die Aufgabe

df
   col_1  col_2
0      0      4
1      1      5
2      2      6
3      3      7

df.reindex(list(df)+['column_new_1', 'column_new_2','column_new_3'], axis=1)
   col_1  col_2  column_new_1  column_new_2  column_new_3
0      0      4           NaN           NaN           NaN
1      1      5           NaN           NaN           NaN
2      2      6           NaN           NaN           NaN
3      3      7           NaN           NaN           NaN

vollständiges Codebeispiel

import numpy as np
import pandas as pd

df = {'col_1': [0, 1, 2, 3],
        'col_2': [4, 5, 6, 7]}
df = pd.DataFrame(df)
print('df',df, sep='\n')
print()
df=df.reindex(list(df)+['column_new_1', 'column_new_2','column_new_3'], axis=1)
print('''df.reindex(list(df)+['column_new_1', 'column_new_2','column_new_3'], axis=1)''',df, sep='\n')

Andernfalls gehen Sie für Null Antwort mit zuweisen

Markus Dutschke
quelle
0

Ich bin nicht zufrieden mit "Index" und so weiter ... könnte wie folgt aussehen

df.columns
Index(['A123', 'B123'], dtype='object')

df=pd.concat([df,pd.DataFrame(columns=list('CDE'))])

df.rename(columns={
    'C':'C123',
    'D':'D123',
    'E':'E123'
},inplace=True)


df.columns
Index(['A123', 'B123', 'C123', 'D123', 'E123'], dtype='object')
Alex
quelle