Dado 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
¿Cuál es la forma más sencilla de agregar una nueva columna que contenga un valor constante, por ejemplo, 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 es mi solución, pero no sé por qué esto coloca a NaN en la columna 'nueva'.
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
df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index)
.[0] * len(df.index)
df['new'] = 0
Respuestas:
La razón por la que esto se coloca
NaN
en una columna es porquedf.index
y losIndex
de su objeto del lado derecho son diferentes. @zach muestra la forma correcta de asignar una nueva columna de ceros. En general,pandas
intenta hacer la mayor alineación de índices posible. Una desventaja es que cuando los índices no están alineados, obtienesNaN
donde no están alineados. Experimente con los métodosreindex
yalign
para obtener algo de intuición sobre los trabajos de alineación con objetos que tienen índices alineados parcial, totalmente y no alineados. Por ejemplo, así es comoDataFrame.align()
funciona con índices parcialmente alineados: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
fuente
Asignación in situ súper simple:
df['new'] = 0
Para modificaciones in situ, realice una asignación directa. Esta asignación es transmitida por pandas para cada fila.
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 columnas de objetos
Si desea agregar una columna de listas vacías, este es mi consejo:
object
las columnas son malas noticias en términos de rendimiento. Reconsidere cómo se estructuran sus datos.Si debe almacenar una columna de listas, asegúrese de no copiar la misma referencia varias veces.
# Wrong df['new'] = [[]] * len(df) # Right df['new'] = [[] for _ in range(len(df))]
Generando una copia:
df.assign(new=0)
Si necesita una copia en su lugar, 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
Y, si necesita asignar varias columnas con el mismo valor, esto es tan simple 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
Asignación de varias columnas
Por último, si necesita asignar varias columnas con diferentes valores, puede utilizarlo
assign
con un diccionario.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
fuente
Con los pandas modernos puedes hacer lo siguiente:
df['new'] = 0
fuente
Aquí hay otro trazador de líneas usando lambdas (cree una columna con un valor constante = 10)
df['newCol'] = df.apply(lambda x: 10, axis=1)
antes de
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
después
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
fuente
df['newCol'] = 10
también es un trazador de líneas (y es más rápido). ¿Cuál es la ventaja de usar aplicar aquí?df['new'] = [[] for _ in range(len(df))]