Spalte mit konstantem Wert zum Pandas-Datenrahmen hinzufügen [Duplikat]

94

Gegeben ein DataFrame:

np.random.seed(0)
df = pd.DataFrame(np.random.randn(3, 3), columns=list('ABC'), index=[1, 2, 3])
df

          A         B         C
1  1.764052  0.400157  0.978738
2  2.240893  1.867558 -0.977278
3  0.950088 -0.151357 -0.103219

Was ist der einfachste Weg, eine neue Spalte hinzuzufügen, die einen konstanten Wert enthält, z. B. 0?

          A         B         C  new
1  1.764052  0.400157  0.978738    0
2  2.240893  1.867558 -0.977278    0
3  0.950088 -0.151357 -0.103219    0

Dies ist meine Lösung, aber ich weiß nicht, warum dies NaN in die 'neue' Spalte bringt?

df['new'] = pd.Series([0 for x in range(len(df.index))])

          A         B         C  new
1  1.764052  0.400157  0.978738  0.0
2  2.240893  1.867558 -0.977278  0.0
3  0.950088 -0.151357 -0.103219  NaN
Yemu
quelle
8
Wenn Sie einen Index verwenden, ist dies in Ordnung. df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
Zach
5
Auch ein Listenverständnis ist hier völlig unnötig. einfach tun[0] * len(df.index)
acushner
@joris, ich meinte, dass df ['new'] = 0 den richtigen Grund für die Zuweisung von Nullen zur gesamten Spalte zeigt, aber es erklärt nicht, warum mein erster Versuch NaN einfügt. Dies wurde von Philip Cloud in der Antwort beantwortet, die ich akzeptierte.
Yemu
6
Einfach machendf['new'] = 0
flow2k

Antworten:

22

Der Grund, warum dies NaNin eine Spalte eingefügt wird, liegt darin, dass df.indexund die IndexIhres rechten Objekts unterschiedlich sind. @zach zeigt den richtigen Weg, um eine neue Spalte mit Nullen zuzuweisen. Im Allgemeinen wird pandasversucht, die Indizes so weit wie möglich auszurichten. Ein Nachteil ist, dass wenn Indizes nicht ausgerichtet sind, Sie NaNüberall dort ankommen, wo sie nicht ausgerichtet sind. Spielen Sie mit den Methoden reindexund herum align, um eine gewisse Intuition für die Ausrichtung zu erlangen. Arbeiten Sie mit Objekten, die teilweise, vollständig und nicht alle ausgerichteten Indizes haben. So DataFrame.align()funktioniert beispielsweise Folgendes mit teilweise ausgerichteten Indizes:

In [7]: from pandas import DataFrame

In [8]: from numpy.random import randint

In [9]: df = DataFrame({'a': randint(3, size=10)})

In [10]:

In [10]: df
Out[10]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [11]: s = df.a[:5]

In [12]: dfa, sa = df.align(s, axis=0)

In [13]: dfa
Out[13]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [14]: sa
Out[14]:
0     0
1     2
2     0
3     1
4     0
5   NaN
6   NaN
7   NaN
8   NaN
9   NaN
Name: a, dtype: float64
Phillip Cloud
quelle
8
Ich habe nicht herabgestimmt, aber Ihr Code enthält keine Kommentare, was es schwierig macht, dem zu folgen, was Sie im Snippet erreichen wollen
Wiedergutmachung
7
Dies beantwortet die Frage nicht wirklich. OP fragt, wie eine neue Spalte mit einem konstanten Wert hinzugefügt werden soll.
CS95
Ich stimme nicht zu, dass es hier nur eine Frage gibt. Es gibt "Wie ordne ich einer Spalte einen konstanten Wert zu?" sowie "Mein Versuch, dies zu tun, funktioniert nicht auf X-Weise. Warum verhält es sich unerwartet?" Ich glaube, ich habe beide Punkte angesprochen, den ersten, indem ich mich auf eine andere Antwort bezog. Bitte lesen Sie den gesamten Text in meiner Antwort.
Phillip Cloud
Ich denke, das Problem liegt eher in der Frage als in Ihrer Antwort. In diesem Beitrag sind zwei unterschiedliche Fragen enthalten. Daher sind zwei unterschiedliche Antworten erforderlich, um die Frage zu beantworten. Ich glaube, dies hätte als zu breit gekennzeichnet werden sollen, und das Poster hätte zwei getrennte Fragen stellen müssen.
Kevin
71

Super einfache In-Place-Zuordnung: df['new'] = 0

Führen Sie zur direkten Änderung eine direkte Zuordnung durch. Diese Aufgabe wird von Pandas für jede Zeile gesendet.

df = pd.DataFrame('x', index=range(4), columns=list('ABC'))
df

   A  B  C
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x

df['new'] = 'y'
# Same as,
# df.loc[:, 'new'] = 'y'
df

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

Hinweis für Objektspalten

Wenn Sie eine Spalte mit leeren Listen hinzufügen möchten, ist hier mein Rat:

  • Erwägen Sie, dies nicht zu tun. objectSpalten sind schlechte Nachrichten in Bezug auf die Leistung. Überdenken Sie die Struktur Ihrer Daten.
  • Erwägen Sie, Ihre Daten in einer spärlichen Datenstruktur zu speichern. Weitere Informationen: spärliche Datenstrukturen
  • Wenn Sie eine Listenspalte speichern müssen, stellen Sie sicher, dass Sie dieselbe Referenz nicht mehrmals kopieren.

    # Wrong
    df['new'] = [[]] * len(df)
    # Right
    df['new'] = [[] for _ in range(len(df))]
    

Kopie erstellen: df.assign(new=0)

Wenn Sie stattdessen eine Kopie benötigen, verwenden Sie DataFrame.assign:

df.assign(new='y')

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

Wenn Sie mehrere solcher Spalten mit demselben Wert zuweisen müssen, ist dies so einfach wie:

c = ['new1', 'new2', ...]
df.assign(**dict.fromkeys(c, 'y'))

   A  B  C new1 new2
0  x  x  x    y    y
1  x  x  x    y    y
2  x  x  x    y    y
3  x  x  x    y    y

Zuordnung mehrerer Spalten

Wenn Sie mehrere Spalten mit unterschiedlichen Werten zuweisen müssen, können Sie diese assignmit einem Wörterbuch verwenden.

c = {'new1': 'w', 'new2': 'y', 'new3': 'z'}
df.assign(**c)

   A  B  C new1 new2 new3
0  x  x  x    w    y    z
1  x  x  x    w    y    z
2  x  x  x    w    y    z
3  x  x  x    w    y    z
cs95
quelle
13

Mit modernen Pandas können Sie einfach Folgendes tun:

df['new'] = 0
Roko Mijic
quelle
1
Können Sie darauf hinweisen, welche konkreten Antworten veraltet sind? Lassen wir einen Kommentar unter ihnen, damit die Autoren die Chance haben, sich zu verbessern.
cs95
Ich denke, die Antwort von Phillip Cloud ist veraltet. Die Antwort von cs95 scheint mir richtig zu sein, aber es macht die Dinge ein bisschen komplizierter, IMO. Dies ist ein einfacher Einzeiler; Zumindest für die gestellte Frage.
Roko Mijic
1
Zu Ihrer Information, der einzige Unterschied zwischen dieser Antwort und der Antwort von cs95 (AKA, me) ist der Spaltenname und der Wert. Alle Stücke sind da.
cs95
7

Hier ist ein weiterer Liner mit Lambdas (Spalte mit konstantem Wert = 10 erstellen)

df['newCol'] = df.apply(lambda x: 10, axis=1)

Vor

df
    A           B           C
1   1.764052    0.400157    0.978738
2   2.240893    1.867558    -0.977278
3   0.950088    -0.151357   -0.103219

nach dem

df
        A           B           C           newCol
    1   1.764052    0.400157    0.978738    10
    2   2.240893    1.867558    -0.977278   10
    3   0.950088    -0.151357   -0.103219   10
Grant Shannon
quelle
4
df['newCol'] = 10ist auch ein Einzeiler (und ist schneller). Was ist der Vorteil der Verwendung hier anwenden?
CS95
1
Ich versuche hier nicht, mit Ihnen zu konkurrieren - ich zeige nur einen alternativen Ansatz.
Grant Shannon
@ cs95 Das ist hilfreich. Ich wollte eine neue Spalte erstellen, in der jeder Wert eine separate leere Liste ist. Nur diese Methode funktioniert.
Yatharth Agarwal
@YatharthAgarwal Das gebe ich dir, aber es macht auch Sinn, wenn Pandas nicht für Listenspalten geeignet sind.
CS95
1
@YatharthAgarwal Wenn Sie leere Listen zuweisen müssen, ist dies immer noch eine unterdurchschnittliche Lösung, da sie anwenden verwendet. Versuchen Siedf['new'] = [[] for _ in range(len(df))]
cs95