Adicionar coluna com valor constante ao dataframe do pandas [duplicado]

98

Dado um 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 é a maneira mais simples de adicionar uma nova coluna contendo um valor constante, por exemplo, 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

Esta é a minha solução, mas não sei por que isso coloca NaN na coluna 'nova'.

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
fonte
9
se você usar um índice está tudo bem. df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
zach
5
além disso, uma compreensão de lista é totalmente desnecessária aqui. basta fazer[0] * len(df.index)
acushner
@joris, quis dizer que df ['new'] = 0 mostra o porquê de atribuir zeros a toda a coluna, mas não explica por que minha primeira tentativa insere NaN. Isso foi respondido pelo Philip Cloud na resposta que aceitei.
yemu
6
Basta fazerdf['new'] = 0
flow2k de

Respostas:

21

A razão pela qual isso é NaNcolocado em uma coluna é porque df.indexe o Indexde seu objeto do lado direito são diferentes. @zach mostra a maneira correta de atribuir uma nova coluna de zeros. Em geral, pandastenta fazer o máximo de alinhamento de índices possível. Uma desvantagem é que, quando os índices não estão alinhados, você obtém tudo o NaNque eles não estão alinhados. Brinque com os métodos reindexe alignpara obter alguma intuição sobre os trabalhos de alinhamento com objetos que possuem índices parcialmente, totalmente e não alinhados. Por exemplo, aqui está como DataFrame.align()funciona com índices parcialmente alinhados:

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
fonte
8
eu não fiz downvote, mas seu código não tem comentários, torna difícil acompanhar o que você está tentando alcançar no trecho
correção
8
Isso realmente não responde à pergunta. OP está perguntando sobre como adicionar uma nova coluna contendo um valor constante.
cs95 de
Não concordo que haja apenas uma pergunta aqui. Há "Como faço para atribuir um valor constante a uma coluna?" e também "Minha tentativa de fazer isso não funciona do modo X, por que está se comportando de maneira inesperada?" Acredito que abordei ambos os pontos, o primeiro referindo-se a outra resposta. Por favor, leia todo o texto em minha resposta.
Phillip Cloud de
Acho que o problema está mais na pergunta do que na sua resposta. Existem duas questões distintas contidas nesta postagem e, como resultado, duas respostas distintas são necessárias para responder à questão. Eu acredito que isso deveria ter sido sinalizado como sendo muito amplo e o pôster deveria ter feito duas perguntas diferentes.
Kevin
74

Atribuição super simples no local: df['new'] = 0

Para modificação no local, execute a atribuição direta. Esta tarefa é transmitida por pandas para cada linha.

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 para colunas de objeto

Se você deseja adicionar uma coluna de listas vazias, aqui está o meu conselho:

  • Considere não fazer isso. objectcolunas são más notícias em termos de desempenho. Repense como seus dados são estruturados.
  • Considere armazenar seus dados em uma estrutura de dados esparsa. Mais informações: estruturas de dados esparsas
  • Se você precisar armazenar uma coluna de listas, certifique-se de não copiar a mesma referência várias vezes.

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

Gerando uma cópia: df.assign(new=0)

Se você precisar de uma cópia, use 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 você precisar atribuir várias dessas colunas com o mesmo valor, isso é tão simples como,

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

Atribuição de múltiplas colunas

Finalmente, se você precisar atribuir várias colunas com valores diferentes, você pode usar assigncom um dicionário.

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
fonte
13

Com os pandas modernos, você pode apenas fazer:

df['new'] = 0
Roko Mijic
fonte
1
Você pode apontar quais respostas específicas estão desatualizadas? Vamos deixar um comentário abaixo deles para que os autores tenham uma chance de melhorar.
cs95
Acho que a resposta de Phillip Cloud está desatualizada. A resposta por cs95 parece correta para mim, mas complica um pouco as coisas, IMO. Esta é uma linha simples mais simples; pelo menos para a pergunta que foi feita.
Roko Mijic
1
Fyi, a única diferença entre esta resposta e a resposta cs95 (também conhecida como eu) é o nome e o valor da coluna. Todas as peças estão lá.
cs95
7

Aqui está outra linha usando lambdas (criar coluna com valor constante = 10)

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

antes

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

depois de

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
fonte
4
df['newCol'] = 10também é um forro (e é mais rápido). Qual é a vantagem de usar aplicar aqui?
cs95 de
1
não tentando competir com você aqui - apenas mostrando uma abordagem alternativa.
Grant Shannon de
@ cs95 Isso é útil. Eu queria criar uma nova coluna em que cada valor fosse uma lista vazia separada. Apenas este método funciona.
Yatharth Agarwal
@YatharthAgarwal Vou te dar isso, mas também faz sentido, já que o pandas não foi projetado para funcionar bem com colunas de listas.
cs95
1
@YatharthAgarwal Se você precisar atribuir listas vazias, esta ainda é uma solução abaixo da média porque usa apply. Experimentedf['new'] = [[] for _ in range(len(df))]
cs95