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 []
acessador
size name color
0 big rose red
1 small violet blue
2 small tulip red
3 small harebell blue
df['protected'] = ['no', 'no', 'no', 'yes']
size name color protected
0 big rose red no
1 small violet blue no
2 small tulip red no
3 small harebell blue yes
Observe que isso funciona mesmo se o índice do quadro de dados estiver desativado.
df.index = [3,2,1,0]
df['protected'] = ['no', 'no', 'no', 'yes']
size name color protected
3 big rose red no
2 small violet blue no
1 small tulip red no
0 small harebell blue yes
[] = é 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:
df['protected'] = pd.Series(['no', 'no', 'no', 'yes'])
size name color protected
3 big rose red yes
2 small violet blue no
1 small tulip red no
0 small harebell blue no
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 a np.ndarray
ou a list
, isso fará o truque.
df['protected'] = pd.Series(['no', 'no', 'no', 'yes']).values
ou
df['protected'] = list(pd.Series(['no', 'no', 'no', 'yes']))
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 de df
é explícito.
df['protected'] = pd.Series(['no', 'no', 'no', 'yes'], index=df.index)
Ou, mais realista, você provavelmente pd.Series
já possui um .
protected_series = pd.Series(['no', 'no', 'no', 'yes'])
protected_series.index = df.index
3 no
2 no
1 no
0 yes
Agora pode ser atribuído
df['protected'] = protected_series
size name color protected
3 big rose red no
2 small violet blue no
1 small tulip red no
0 small harebell blue yes
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.
df.reset_index(drop=True)
protected_series.reset_index(drop=True)
df['protected'] = protected_series
size name color protected
0 big rose red no
1 small violet blue no
2 small tulip red no
3 small harebell blue yes
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[]=
df.assign(protected=pd.Series(['no', 'no', 'no', 'yes']))
size name color protected
3 big rose red yes
2 small violet blue no
1 small tulip red no
0 small harebell blue no
Apenas observe df.assign
que sua coluna não é chamada self
. Isso causará erros. Isso torna df.assign
fedorento , pois existem esses tipos de artefatos na função.
df.assign(self=pd.Series(['no', 'no', 'no', 'yes'])
TypeError: assign() got multiple values for keyword argument 'self'
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.