Use os índices df1 originais para criar a série:
df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
Edit 2015
Alguns relataram ter recebido SettingWithCopyWarning
este código.
No entanto, o código ainda funciona perfeitamente com a versão 0.16.1 do pandas atual.
>>> sLength = len(df1['a'])
>>> df1
a b c d
6 -0.269221 -0.026476 0.997517 1.294385
8 0.917438 0.847941 0.034235 -0.448948
>>> df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
a b c d e
6 -0.269221 -0.026476 0.997517 1.294385 1.757167
8 0.917438 0.847941 0.034235 -0.448948 2.228131
>>> p.version.short_version
'0.16.1'
O SettingWithCopyWarning
objetivo é informar sobre uma atribuição possivelmente inválida em uma cópia do Dataframe. Não significa necessariamente que você fez errado (pode disparar falsos positivos), mas a partir de 0.13.0, você sabe que existem métodos mais adequados para o mesmo objetivo. Então, se você receber o aviso, basta seguir o aviso: Tente usar .loc [row_index, col_indexer] = value
>>> df1.loc[:,'f'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
a b c d e f
6 -0.269221 -0.026476 0.997517 1.294385 1.757167 -0.050927
8 0.917438 0.847941 0.034235 -0.448948 2.228131 0.006109
>>>
De fato, atualmente esse é o método mais eficiente, conforme descrito em documentos de pandas
Edit 2017
Conforme indicado nos comentários e pelo @Alexander, atualmente o melhor método para adicionar os valores de uma Série como uma nova coluna de um DataFrame poderia estar usando assign
:
df1 = df1.assign(e=pd.Series(np.random.randn(sLength)).values)
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead
kwargs
dicionário da seguinte maneira:df1 = df1.assign(**{'e': p.Series(np.random.randn(sLength)).values})
Esta é a maneira simples de adicionar uma nova coluna:
df['e'] = e
fonte
e
(Series(np.random.randn(sLength))
) gera uma série 0-n indexada. Se você atribuir isso ao df1, receberá algumas células NaN.my_dataframe = pd.DataFrame(columns=('foo', 'bar'))
. Revertendo sua ediçãoSuponho que os valores do índice
e
correspondam aos valoresdf1
.A maneira mais fácil de iniciar uma nova coluna denominada
e
e atribuir os valores de sua sériee
:atribuir (Pandas 0.16.0+)
No Pandas 0.16.0, você também pode usar
assign
, que atribui novas colunas a um DataFrame e retorna um novo objeto (uma cópia) com todas as colunas originais, além das novas.Conforme este exemplo (que também inclui o código fonte da
assign
função), você também pode incluir mais de uma coluna:No contexto do seu exemplo:
A descrição desse novo recurso, quando foi introduzido pela primeira vez, pode ser encontrada aqui .
fonte
df['e'] = e.values
) não cria uma cópia do quadro de dados, enquanto a segunda opção (usandodf.assign
) cria ? No caso de muitas novas colunas serem adicionadas sequencialmente e grandes quadros de dados, eu esperaria um desempenho muito melhor do primeiro método.assign
é quando encadear suas operações.df.assign(**df.mean().add_prefix('mean_'))
df_new = pd.concat([df1, df2], axis=1)
, observando issoignore_index=False
por padrão.Parece que nas versões recentes do Pandas o caminho a seguir é usar o df.assign :
df1 = df1.assign(e=np.random.randn(sLength))
Não produz
SettingWithCopyWarning
.fonte
Fazer isso diretamente via NumPy será o mais eficiente:
Observe que minha sugestão original (muito antiga) era usar
map
(que é muito mais lenta):fonte
.map
para usar as séries existentes em vez delambda
? Eu tentodf1['e'] = df1['a'].map(lambda x: e)
oudf1['e'] = df1['a'].map(e)
mas não é o que eu preciso. (Eu sou novo para pyhon e sua resposta anterior já me ajudou)e
uma série, não precisa usarmap
, usedf['e']=e
(@joaquins answer).Atribuição de coluna super simples
Um dataframe do pandas é implementado como um ditado ordenado de colunas.
Isso significa que
__getitem__
[]
não só pode ser usado para obter uma determinada coluna, mas__setitem__
[] =
também para atribuir uma nova coluna.Por exemplo, esse quadro de dados pode ter uma coluna adicionada a ele simplesmente usando o
[]
acessadorObserve que isso funciona mesmo se o índice do quadro de dados estiver desativado.
[] = é o caminho a seguir, mas cuidado!
No entanto, se você tiver um
pd.Series
e tentar atribuí-lo a um dataframe em que os índices estejam desativados, você terá problemas. Consultar exemplo:Isso ocorre porque um
pd.Series
por padrão tem um índice enumerado de 0 a n. E o[] =
método dos pandas tenta ser "inteligente"O que realmente está acontecendo.
Quando você usa o
[] =
método, o pandas realiza silenciosamente uma junção externa ou mesclagem externa usando o índice do quadro de dados à esquerda e o índice da série à direita.df['column'] = series
Nota
Isso rapidamente causa dissonância cognitiva, pois o
[]=
método está tentando fazer muitas coisas diferentes, dependendo da entrada, e o resultado não pode ser previsto, a menos que você saiba como os pandas funcionam. Eu recomendaria, portanto, contra as[]=
bases de código, mas ao explorar dados em um notebook, tudo bem.Contornando o problema
Se você tem um
pd.Series
e deseja que ele seja atribuído de cima para baixo, ou se está codificando código produtivo e não tem certeza da ordem do índice, vale a pena salvaguardar esse tipo de problema.Você pode fazer o downcast
pd.Series
para anp.ndarray
ou alist
, isso fará o truque.ou
Mas isso não é muito explícito.
Algum codificador pode aparecer e dizer "Ei, isso parece redundante, vou otimizar isso daqui".
Maneira explícita
Definir o índice de
pd.Series
como o índice dedf
é explícito.Ou, mais realista, você provavelmente
pd.Series
já possui um .Agora pode ser atribuído
Maneira alternativa com
df.reset_index()
Como a dissonância do índice é o problema, se você acha que o índice do quadro de dados não deve ditar as coisas, você pode simplesmente descartá - lo, isso deve ser mais rápido, mas não é muito limpo, pois sua função agora provavelmente faz duas coisas.
Nota sobre
df.assign
Embora
df.assign
torne mais explícito o que você está fazendo, ele realmente tem os mesmos problemas que os mencionados acima[]=
Apenas observe
df.assign
que sua coluna não é chamadaself
. Isso causará erros. Isso tornadf.assign
fedorento , pois existem esses tipos de artefatos na função.Você pode dizer: "Bem, eu não usarei
self
então". Mas quem sabe como essa função muda no futuro para suportar novos argumentos. Talvez o nome da sua coluna seja um argumento em uma nova atualização do pandas, causando problemas com a atualização.fonte
[] =
método, o pandas realiza silenciosamente uma junção externa ou mesclagem externa ". Esta é a informação mais importante em todo o tópico. Mas você poderia fornecer um link para a documentação oficial sobre como o[]=
operador funciona?Maneiras mais fáceis: -
Dessa forma, você evita o que é chamado de indexação encadeada ao definir novos valores em um objeto pandas. Clique aqui para ler mais .
fonte
Se você deseja definir toda a nova coluna com um valor base inicial (por exemplo
None
), você pode fazer isso:df1['e'] = None
Na verdade, isso atribuiria o tipo "objeto" à célula. Mais tarde, você poderá inserir tipos de dados complexos, como lista, em células individuais.
fonte
Eu peguei o temido
SettingWithCopyWarning
e não foi corrigido usando a sintaxe iloc. Meu DataFrame foi criado por read_sql a partir de uma fonte ODBC. Usando uma sugestão da lowtech acima, o seguinte funcionou para mim:Isso funcionou bem para inserir a coluna no final. Não sei se é o mais eficiente, mas não gosto de mensagens de aviso. Eu acho que existe uma solução melhor, mas não consigo encontrá-la e acho que depende de algum aspecto do índice.
Nota . Isso só funciona uma vez e dará uma mensagem de erro se você tentar substituir a coluna existente.
Nota Como acima e da 0.16.0, assign é a melhor solução. Consulte a documentação http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign Funciona bem para o tipo de fluxo de dados em que você não substitui seus valores intermediários.
fonte
list_of_e
com dados relevantes.df['e'] = list_of_e
fonte
tolist()
comando pode ser útil.Se a coluna que você está tentando adicionar for uma variável em série, basta:
Isso funciona bem mesmo se você estiver substituindo uma coluna existente. Apenas digite new_columns_name igual à coluna que deseja substituir. Ele substituirá apenas os dados da coluna existente pelos novos dados da série.
fonte
Se o quadro de dados e o objeto Series tiverem o mesmo índice ,
pandas.concat
também funcionará aqui:Caso eles não tenham o mesmo índice:
fonte
Infalível:
Exemplo:
fonte
Deixe-me acrescentar que, assim como no hum3 ,
.loc
não resolveu o problemaSettingWithCopyWarning
e tive que recorrerdf.insert()
. No meu caso, o falso positivo foi gerado pela indexação em cadeia "falsa"dict['a']['e']
, onde'e'
está a nova coluna edict['a']
é um DataFrame vindo do dicionário.Observe também que, se você souber o que está fazendo, poderá mudar o aviso usando
pd.options.mode.chained_assignment = None
e depois usando uma das outras soluções fornecidas aqui.fonte
para inserir uma nova coluna em um determinado local (0 <= loc <= quantidade de colunas) em um quadro de dados, basta usar Dataframe.insert:
Portanto, se você desejar adicionar a coluna e no final de um quadro de dados chamado df , poderá usar:
O valor pode ser uma série, um número inteiro (nesse caso, todas as células são preenchidas com esse valor único) ou uma estrutura semelhante a uma matriz
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.insert.html
fonte
Antes de atribuir uma nova coluna, se você tiver dados indexados, precisará classificar o índice. Pelo menos no meu caso eu tive que:
fonte
Uma coisa a observar, porém, é que, se você fizer
isso efetivamente será uma junção esquerda no df1.index. Portanto, se você deseja ter um efeito de junção externa , minha solução provavelmente imperfeita é criar um quadro de dados com valores de índice que cubram o universo dos seus dados e, em seguida, use o código acima. Por exemplo,
fonte
Eu estava procurando uma maneira geral de adicionar uma coluna de
numpy.nan
s a um dataframe sem ser burroSettingWithCopyWarning
.Entre o seguinte:
numpy
matriz de NaNs em linhaEu vim com isso:
fonte
Para adicionar uma nova coluna, 'e', ao quadro de dados existente
fonte
Por uma questão de integridade - mais uma solução usando o método DataFrame.eval () :
Dados:
Solução:
fonte
Para criar uma coluna vazia
fonte
A seguir, o que eu fiz ... Mas eu sou muito novo em pandas e realmente em Python em geral, então não há promessas.
fonte
Se você obtiver o
SettingWithCopyWarning
, uma solução fácil é copiar o DataFrame ao qual você está tentando adicionar uma coluna.fonte