Fügen Sie Pandas DataFrame mehrere leere Spalten hinzu


74

Wie füge ich DataFrameeiner Liste mehrere leere Spalten hinzu ?

Ich kann:

    df["B"] = None
    df["C"] = None
    df["D"] = None

Aber ich kann nicht tun:

    df[["B", "C", "D"]] = None

KeyError: "['B' 'C' 'D'] not in index"


Noneist anders als 0, aber einige Antworten gehen davon aus, dass es äquivalent ist. NoneWenn Sie zuweisen , erhalten Sie einen Objekttyp d. Wenn Sie jedoch 0 zuweisen, erhalten Sie einen Objekttyp int.
smci

Auch können Sie nicht df[['B','C','D']] = None, None, Noneoder [None, None, None]oderpd.DataFrame([None, None, None])
smci

Verwandte Themen
smci

Antworten:


70

Ich würde concateinen DataFrame verwenden:

In [23]:
df = pd.DataFrame(columns=['A'])
df

Out[23]:
Empty DataFrame
Columns: [A]
Index: []

In [24]:    
pd.concat([df,pd.DataFrame(columns=list('BCD'))])

Out[24]:
Empty DataFrame
Columns: [A, B, C, D]
Index: []

Wenn Sie also eine Liste mit Ihrem ursprünglichen df und eine neue Liste mit den Spalten übergeben, die Sie hinzufügen möchten, wird ein neuer df mit den zusätzlichen Spalten zurückgegeben.


Vorsichtsmaßnahme: Siehe die Diskussion der Leistung in den anderen Antworten und / oder den Kommentardiskussionen. reindexkann vorzuziehen sein, wenn die Leistung kritisch ist.


Danke, es ist möglich, dass mir etwas fehlt, aber ich habe hinzugefügt pd.concat([df,pd.DataFrame(columns=list('BCD'))])- es macht nichts afaik. Könnte es daran liegen, dass ich benutze df = pd.read_csvund nicht df = pd.DataFrame?
PAN

2
Sie müssen das Ergebnis des Konkats so df=pd.concat([df,pd.DataFrame(columns=list('BCD'))])
zuweisen

1
Das sollte nicht passieren, Sie können die Spaltenreihenfolge entweder durch ausgefallene Indizierung ändern: df.ix[:, col_list]oder indem Sie sie einfach auswählen und wieder dem ursprünglichen df df = df[col_list]
zuweisen

1
Dies funktioniert nicht mehr (mit Pandas 0.19.1). Die Verkettung führt zu a TypeError: data type not understood.
Thenaturalist

1
@thenaturalist Entschuldigung, das funktioniert immer noch für mich in Pandas. 0.19.1Sie müssen den vollständigen Code posten, den ich ausführen kann
EdChum

77

Sie können verwenden df.reindex, um neue Spalten hinzuzufügen:

In [18]: df = pd.DataFrame(np.random.randint(10, size=(5,1)), columns=['A'])

In [19]: df
Out[19]: 
   A
0  4
1  7
2  0
3  7
4  6

In [20]: df.reindex(columns=list('ABCD'))
Out[20]: 
   A   B   C   D
0  4 NaN NaN NaN
1  7 NaN NaN NaN
2  0 NaN NaN NaN
3  7 NaN NaN NaN
4  6 NaN NaN NaN

reindex gibt einen neuen DataFrame zurück, wobei die Spalten in der angegebenen Reihenfolge angezeigt werden:

In [31]: df.reindex(columns=list('DCBA'))
Out[31]: 
    D   C   B  A
0 NaN NaN NaN  4
1 NaN NaN NaN  7
2 NaN NaN NaN  0
3 NaN NaN NaN  7
4 NaN NaN NaN  6

Die reindexMethode auch als fill_valueParameter:

In [22]: df.reindex(columns=list('ABCD'), fill_value=0)
Out[22]: 
   A  B  C  D
0  4  0  0  0
1  7  0  0  0
2  0  0  0  0
3  7  0  0  0
4  6  0  0  0

4
Nach dem Experimentieren mit einem mäßig großen Datenrahmen (~ 2,5.000 Zeilen für 80.000 Spalten) scheint diese Lösung um Größenordnungen schneller zu sein als die akzeptierte. Übrigens gibt es einen Grund, warum dieser spezielle Befehl kein "inplace = True" akzeptiert "Parameter? df = df.reindex (...) scheint ziemlich viel RAM zu verbrauchen.
Marco Spinaci

5
@ MarcoSpinaci: Ich empfehle, nie zu verwenden inplace=True. Es macht nicht das, was die meisten Leute denken. Unter der Haube wird immer ein völlig neuer DataFrame erstellt, und dann werden die Daten aus dem neuen DataFrame in den ursprünglichen DataFrame kopiert. Das spart keinen Speicher. So inplace=Trueist Schaufensterdekoration ohne Substanz und wird darüber hinaus irreführend benannt. Ich habe den Code nicht überprüft, aber ich gehe davon aus, df = df.reindex(...)dass mindestens das Zweifache des erforderlichen Speichers erforderlich ist df, und natürlich mehr, wenn reindexdie Anzahl der Zeilen erweitert wird.
Unutbu

@unutbu, dennoch ist es nützlich, wenn Sie Container iterieren, z. B. eine Liste oder ein Wörterbuch, es würde die Verwendung von Indizes vermeiden, die den Code ein bisschen schmutziger machen ...
toto_tico

@unutbu es ist in der Tat viel schneller, wenn ich meinen ~ 200-Spalten-Erstellungscode profiliert habe. Können Sie kurz erklären, warum die Neuindizierung viel schneller ist als concat oder einfach mehrere Spalten auf ein numpy-Array setzen?
Sam

34

Wenn Sie den Namen der alten Spalten nicht neu schreiben möchten, können Sie reindex verwenden:

df.reindex(columns=[*df.columns.tolist(), 'new_column1', 'new_column2'], fill_value=0)

Vollständiges Beispiel :

In [1]: df = pd.DataFrame(np.random.randint(10, size=(3,1)), columns=['A'])

In [1]: df
Out[1]: 
   A
0  4
1  7
2  0

In [2]: df.reindex(columns=[*df.columns.tolist(), 'col1', 'col2'], fill_value=0)
Out[2]: 

   A  col1  col2
0  1     0     0
1  2     0     0

Und wenn Sie bereits eine Liste mit den Spaltennamen haben ,:

In [3]: my_cols_list=['col1','col2']

In [4]: df.reindex(columns=[*df.columns.tolist(), *my_cols_list], fill_value=0)
Out[4]: 
   A  col1  col2
0  1     0     0
1  2     0     0

2
Vielen Dank. Könnten Sie mir bitte sagen, was das *in der reindexEingabe macht?
Bowen Liu

2
Es entpackt die Liste in Positionsargumente, es ist ein Python-Operator
toto_tico

5

Warum nicht einfach loop verwenden:

for newcol in ['B','C','D']:
    df[newcol]=np.nan

0 ist nicht der gleiche Wert wie None. Außerdem wird der dtype auf eine Ganzzahl gezwungen, während dies bei None nicht der Fall ist.
smci

1

Zusammenfassung alternativer Lösungen:

columns_add = ['a', 'b', 'c']
  1. for-Schleife:

    for newcol in columns_add:
        df[newcol]= None
    
  2. Diktiermethode:

    df.assign(**dict([(_,None) for _ in columns_add]))
    
  3. Tupelzuordnung:

    df['a'], df['b'], df['c'] = None, None, None
    

0

Nur um der Liste der lustigen Möglichkeiten hinzuzufügen:

columns_add = ['a', 'b', 'c']
df = df.assign(**dict(zip(columns_add, [0] * len(columns_add)))

0 ist nicht der gleiche Wert wie None. Außerdem wird der dtype auf eine Ganzzahl gezwungen, während dies bei None nicht der Fall ist.
smci

Auf jeden Fall fehlt Ihnen eine nachfolgende vierte enge Klammer.
smci

0

Ich würde verwenden

df["B"], df["C"], df["D"] = None, None, None

oder

df["B"], df["C"], df["D"] = ["None" for a in range(3)]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.