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"

PFANNE
quelle
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.

EdChum
quelle
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
unutbu
quelle
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
toto_tico
quelle
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
alexprice
quelle
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
    
yosemite_k
quelle
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)))
Oleg O.
quelle
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)]
lumiere_profues
quelle