Hubiera esperado que tu sintaxis también funcionara. El problema surge porque cuando crea nuevas columnas con la sintaxis de lista de columnas ( df[[new1, new2]] = ...
), pandas requiere que el lado derecho sea un DataFrame (tenga en cuenta que en realidad no importa si las columnas del DataFrame tienen los mismos nombres que las columnas estás creando).
Su sintaxis funciona bien para asignar valores escalares a columnas existentes , y los pandas también están felices de asignar valores escalares a una nueva columna usando la sintaxis de una sola columna ( df[new1] = ...
). Entonces, la solución es convertir esto en varias asignaciones de una sola columna o crear un DataFrame adecuado para el lado derecho.
Aquí hay varios enfoques que se trabajarán:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'col_1': [0, 1, 2, 3],
'col_2': [4, 5, 6, 7]
})
Entonces uno de los siguientes:
1) Tres asignaciones en una, utilizando el desempaquetado de listas:
df['column_new_1'], df['column_new_2'], df['column_new_3'] = [np.nan, 'dogs', 3]
2) DataFrame
expande convenientemente una sola fila para que coincida con el índice, por lo que puede hacer esto:
df[['column_new_1', 'column_new_2', 'column_new_3']] = pd.DataFrame([[np.nan, 'dogs', 3]], index=df.index)
3) Cree un marco de datos temporal con nuevas columnas, luego combínelo con el marco de datos original más tarde:
df = pd.concat(
[
df,
pd.DataFrame(
[[np.nan, 'dogs', 3]],
index=df.index,
columns=['column_new_1', 'column_new_2', 'column_new_3']
)
], axis=1
)
4) Similar al anterior, pero usando en join
lugar de concat
(puede ser menos eficiente):
df = df.join(pd.DataFrame(
[[np.nan, 'dogs', 3]],
index=df.index,
columns=['column_new_1', 'column_new_2', 'column_new_3']
))
5) Usar un dictado es una forma más "natural" de crear el nuevo marco de datos que los dos anteriores, pero las nuevas columnas se ordenarán alfabéticamente (al menos antes de Python 3.6 o 3.7 ):
df = df.join(pd.DataFrame(
{
'column_new_1': np.nan,
'column_new_2': 'dogs',
'column_new_3': 3
}, index=df.index
))
6) Úselo .assign()
con argumentos de varias columnas.
Me gusta mucho esta variante en la respuesta de @ zero, pero al igual que la anterior, las nuevas columnas siempre se ordenarán alfabéticamente, al menos con las primeras versiones de Python:
df = df.assign(column_new_1=np.nan, column_new_2='dogs', column_new_3=3)
new_cols = ['column_new_1', 'column_new_2', 'column_new_3']
new_vals = [np.nan, 'dogs', 3]
df = df.reindex(columns=df.columns.tolist() + new_cols) # add empty cols
df[new_cols] = new_vals # multi-column assignment works for existing cols
8) Al final, es difícil superar tres asignaciones distintas:
df['column_new_1'] = np.nan
df['column_new_2'] = 'dogs'
df['column_new_3'] = 3
Nota: muchas de estas opciones ya se han cubierto en otras respuestas: agregue varias columnas a DataFrame y configúrelas igual a una columna existente . ¿Es posible agregar varias columnas a la vez a un DataFrame de pandas? , Agregue múltiples columnas vacías a pandas DataFrame
KeyError: "None of [Index(['column_new_1', 'column_new_2', 'column_new_3'], dtype='object')] are in the [columns]"