Aggiungi colonna con valore costante al dataframe panda [duplicato]


102

Dato un 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

Qual è il modo più semplice per aggiungere una nuova colonna contenente un valore costante, ad esempio 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

Questa è la mia soluzione, ma non so perché inserisca NaN nella colonna "nuova"?

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

9
se usi un indice va bene. df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
zach

5
inoltre, una comprensione dell'elenco è del tutto inutile qui. basta fare[0] * len(df.index)
acushner

@joris, volevo dire che df ['new'] = 0 mostra il motivo corretto di assegnare zeri all'intera colonna, ma non spiega perché il mio primo tentativo inserisce NaN. Questo è stato risposto dal Philip Cloud nella risposta che ho accettato.
yemu

7
df['new'] = 0
Fallo

Risposte:


21

Il motivo per cui questo viene inserito NaNin una colonna è perché df.indexe il Indexdel tuo oggetto a destra sono diversi. @zach mostra il modo corretto per assegnare una nuova colonna di zeri. In generale, pandascerca di fare il maggior allineamento possibile degli indici. Uno svantaggio è che quando gli indici non sono allineati si arriva NaNovunque non siano allineati. Gioca con i metodi reindexe alignper ottenere un po 'di intuizione per i lavori di allineamento con oggetti che hanno indici allineati parzialmente, totalmente e non allineati. Ad esempio, ecco come DataFrame.align()funziona con indici parzialmente allineati:

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

10
Non ho votato negativamente ma il tuo codice manca di commenti, rende difficile seguire quello che stai cercando di ottenere nello snippet
correggere il

8
Questo non risponde davvero alla domanda. OP chiede come aggiungere una nuova colonna contenente un valore costante.
cs95

Non sono d'accordo che qui ci sia solo una domanda. C'è "Come si assegna un valore costante a una colonna?" così come "Il mio tentativo di farlo non funziona in modo X, perché si comporta in modo imprevisto?" Credo di aver affrontato entrambi i punti, il primo facendo riferimento a un'altra risposta. Si prega di leggere tutto il testo nella mia risposta.
Phillip Cloud

Penso che il problema sia con la domanda piuttosto che con la tua risposta. Ci sono due domande distinte contenute in questo post e di conseguenza sono necessarie due risposte distinte per rispondere alla domanda. Credo che questo avrebbe dovuto essere contrassegnato come troppo ampio e il poster avrebbe dovuto porre due domande separate.
Kevin

83

Assegnazione sul posto super semplice: df['new'] = 0

Per la modifica sul posto, eseguire l'assegnazione diretta. Questo incarico viene trasmesso dai panda per ogni riga.

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

Nota per le colonne degli oggetti

Se vuoi aggiungere una colonna di elenchi vuoti, ecco il mio consiglio:

  • Considera di non farlo. objectle colonne sono cattive notizie in termini di prestazioni. Ripensa a come sono strutturati i tuoi dati.
  • Considera l'idea di archiviare i tuoi dati in una struttura di dati sparsa. Ulteriori informazioni: strutture dati sparse
  • Se è necessario memorizzare una colonna di elenchi, assicurarsi di non copiare più volte lo stesso riferimento.

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

Generazione di una copia: df.assign(new=0)

Se invece ti serve una copia, usa 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

E, se è necessario assegnare più colonne di questo tipo con lo stesso valore, è semplice come,

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

Assegnazione di più colonne

Infine, se è necessario assegnare più colonne con valori diversi, è possibile utilizzarle assigncon un dizionario.

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

18

Con i panda moderni puoi semplicemente fare:

df['new'] = 0

1
Puoi indicare quali risposte specifiche non sono aggiornate? Lasciamo un commento sotto di loro in modo che gli autori abbiano la possibilità di migliorare.
cs95

1
Fyi l'unica differenza tra questa risposta e la risposta cs95 (AKA, me) è il nome e il valore della colonna. Tutti i pezzi sono lì.
cs95

1
Non è tanto che siano obsoleti, ma questa risposta è meno prolissa delle altre ed è più facile da leggere.
Joey

1
@Joey Non posso discutere con questa logica, suppongo che questa risposta sia più adatta a persone che stanno solo cercando di copiare e incollare qualsiasi cosa che funzioni, piuttosto che cercare di capire e imparare di più sulla libreria. Touche.
cs95

1
@ cs95 sì, la tua risposta consente alle persone di saperne di più. Anche il df ['new'] = 0 evidenziato nel titolo è buono per la leggibilità. Anch'io ho votato al contrario. Meno prolisso di df.apply (lambda x: 0, axis = 1)
Joey

7

Ecco un altro liner che usa lambda (crea colonna con valore costante = 10)

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

prima

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

dopo

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

5
df['newCol'] = 10è anche un one liner (ed è più veloce). Qual è il vantaggio di utilizzare applica qui?
cs95

2
non cercare di competere con te qui, ma solo mostrare un approccio alternativo.
Grant Shannon

@ cs95 Questo è utile. Volevo creare una nuova colonna in cui ogni valore fosse un elenco vuoto separato. Solo questo metodo funziona.
Yatharth Agarwal

@YatharthAgarwal Te lo do, ma ha anche senso dato che i panda non sono progettati per funzionare bene con colonne di elenchi.
cs95

1
@YatharthAgarwal Se è necessario assegnare elenchi vuoti, questa è ancora una soluzione scadente perché utilizza apply. Provadf['new'] = [[] for _ in range(len(df))]
cs95
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.