Use los índices df1 originales para crear la serie:
df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
Editar 2015
Algunos informaron que obtuvieron el SettingWithCopyWarning
con este código.
Sin embargo, el código aún funciona perfectamente con la versión actual de pandas 0.16.1.
>>> 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'
El SettingWithCopyWarning
objetivo es informar de una asignación posiblemente no válida en una copia del Marco de datos. No necesariamente dice que lo hizo mal (puede desencadenar falsos positivos), pero desde 0.13.0 le informa que hay métodos más adecuados para el mismo propósito. Luego, si recibe la advertencia, solo siga sus consejos: intente usar .loc [row_index, col_indexer] = value en su lugar
>>> 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 hecho, este es actualmente el método más eficiente como se describe en los documentos de pandas
Editar 2017
Como se indica en los comentarios y por @Alexander, actualmente el mejor método para agregar los valores de una Serie como una nueva columna de un DataFrame podría 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
diccionario, así:df1 = df1.assign(**{'e': p.Series(np.random.randn(sLength)).values})
Esta es la manera simple de agregar una nueva columna:
df['e'] = e
fuente
e
(Series(np.random.randn(sLength))
) genera una Serie 0-n indexada. Si asigna esto a df1, obtendrá algunas celdas de NaN.my_dataframe = pd.DataFrame(columns=('foo', 'bar'))
. Revertir su ediciónSupongo que los valores del índice en
e
coinciden con los dedf1
.La forma más fácil de iniciar una nueva columna llamada
e
y asignarle los valores de su seriee
:asignar (Pandas 0.16.0+)
A partir de Pandas 0.16.0, también puede usar
assign
, que asigna nuevas columnas a un DataFrame y devuelve un nuevo objeto (una copia) con todas las columnas originales además de las nuevas.Según este ejemplo (que también incluye el código fuente de la
assign
función), también puede incluir más de una columna:En contexto con tu ejemplo:
La descripción de esta nueva característica cuando se introdujo por primera vez se puede encontrar aquí .
fuente
df['e'] = e.values
) no crea una copia del marco de datos, mientras que la segunda opción (usardf.assign
) sí? En el caso de que se agreguen muchas columnas nuevas secuencialmente y grandes marcos de datos, esperaría un rendimiento mucho mejor del primer método.assign
es cuando encadena sus operaciones.df.assign(**df.mean().add_prefix('mean_'))
df_new = pd.concat([df1, df2], axis=1)
, notándoloignore_index=False
de manera predeterminada.Parece que en versiones recientes de Pandas, el camino a seguir es usar df.assign :
df1 = df1.assign(e=np.random.randn(sLength))
No produce
SettingWithCopyWarning
.fuente
Hacer esto directamente a través de NumPy será lo más eficiente:
Tenga en cuenta que mi sugerencia original (muy antigua) era usar
map
(que es mucho más lento):fuente
.map
para usar series existentes en lugar delambda
? Lo intentodf1['e'] = df1['a'].map(lambda x: e)
odf1['e'] = df1['a'].map(e)
no, pero no es lo que necesito. (Soy nuevo en pyhon y su respuesta anterior ya me ayudó)e
como Serie, entonces no necesita usarmap
, usedf['e']=e
(respuesta @joaquins).Asignación de columna super simple
Un marco de datos de pandas se implementa como un dict ordenado de columnas.
Esto significa que
__getitem__
[]
no solo se puede usar para obtener una determinada columna, sino que__setitem__
[] =
se puede usar para asignar una nueva columna.Por ejemplo, este marco de datos puede tener una columna agregada simplemente usando el descriptor de
[]
accesoTenga en cuenta que esto funciona incluso si el índice del marco de datos está desactivado.
[] = es el camino a seguir, ¡pero cuidado!
Sin embargo, si tiene un
pd.Series
e intenta asignarlo a un marco de datos donde los índices están apagados, se encontrará con problemas. Ver ejemplo:Esto se debe a que
pd.Series
por defecto tiene un índice enumerado de 0 a n. Y el[] =
método de los pandas intenta ser "inteligente"Lo que realmente está pasando.
Cuando usas el
[] =
método, pandas realiza silenciosamente una combinación externa o una combinación externa utilizando el índice del marco de datos de la izquierda y el índice de la serie de la derecha.df['column'] = series
Nota al margen
Esto rápidamente causa disonancia cognitiva, ya que el
[]=
método está tratando de hacer muchas cosas diferentes dependiendo de la entrada, y el resultado no puede predecirse a menos que solo sepa cómo funcionan los pandas. Por lo tanto, aconsejaría contra las[]=
bases de código, pero al explorar datos en un cuaderno, está bien.Dando la vuelta al problema
Si tiene un
pd.Series
y desea asignarlo de arriba a abajo, o si está codificando código productivo y no está seguro del orden del índice, vale la pena salvaguardarlo para este tipo de problema.Podrías abatir el
pd.Series
a anp.ndarray
o alist
, esto hará el truco.o
Pero esto no es muy explícito.
Algún codificador puede venir y decir "Oye, esto parece redundante, simplemente lo optimizaré".
Manera explícita
Establecer el índice de
pd.Series
ser el índice dedf
es explícito.O de manera más realista, es probable que
pd.Series
ya tenga una disponible.Ahora se puede asignar
Forma alternativa con
df.reset_index()
Dado que la disonancia del índice es el problema, si considera que el índice del marco de datos no debe dictar cosas, simplemente puede soltar el índice, esto debería ser más rápido, pero no es muy limpio, ya que su función ahora probablemente hace dos cosas.
Nota sobre
df.assign
Si bien
df.assign
es más explícito lo que está haciendo, en realidad tiene los mismos problemas que los anteriores[]=
Solo ten cuidado con
df.assign
que tu columna no se llameself
. Causará errores. Esto hacedf.assign
mal olor , ya que hay este tipo de artefactos en la función.Puede decir: "Bueno,
self
entonces no lo usaré ". Pero quién sabe cómo cambia esta función en el futuro para respaldar nuevos argumentos. Tal vez el nombre de su columna sea un argumento en una nueva actualización de pandas, causando problemas con la actualización.fuente
[] =
método, pandas realiza silenciosamente una combinación o fusión externa ". Esta es la información más importante en todo el tema. Pero, ¿podría proporcionar un enlace a la documentación oficial sobre cómo[]=
funciona el operador?Formas más fáciles: -
De esta manera, evita lo que se denomina indexación encadenada al establecer nuevos valores en un objeto pandas. Haga clic aquí para leer más .
fuente
Si desea establecer toda la nueva columna en un valor base inicial (p. Ej.
None
), puede hacer esto:df1['e'] = None
Esto realmente asignaría el tipo de "objeto" a la celda. Así que más tarde puede colocar tipos de datos complejos, como list, en celdas individuales.
fuente
SettingWithCopyWarning
Obtuve el temido , y no se solucionó utilizando la sintaxis iloc. Mi DataFrame fue creado por read_sql de una fuente ODBC. Usando una sugerencia de lowtech anterior, lo siguiente funcionó para mí:Esto funcionó bien para insertar la columna al final. No sé si es el más eficiente, pero no me gustan los mensajes de advertencia. Creo que hay una mejor solución, pero no puedo encontrarla, y creo que depende de algún aspecto del índice.
Nota . Que esto solo funciona una vez y dará un mensaje de error si intenta sobrescribir una columna existente.
Nota Como arriba y desde 0.16.0 asignar es la mejor solución. Consulte la documentación http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign Funciona bien para el tipo de flujo de datos donde no sobrescribe sus valores intermedios.
fuente
list_of_e
que tenga datos relevantes.df['e'] = list_of_e
fuente
tolist()
comando puede ser útil.Si la columna que está intentando agregar es una variable en serie, simplemente:
Esto funciona bien incluso si está reemplazando una columna existente. Simplemente escriba new_columns_name igual que la columna que desea reemplazar. Simplemente sobrescribirá los datos de la columna existente con los datos de la nueva serie.
fuente
Si el marco de datos y el objeto Serie tienen el mismo índice ,
pandas.concat
también funciona aquí:En caso de que no tengan el mismo índice:
fuente
Infalible:
Ejemplo:
fuente
Permítanme agregar que, al igual que para hum3 ,
.loc
no resolvió el problemaSettingWithCopyWarning
y tuve que recurrir a éldf.insert()
. En mi caso, se generó falso positivo por la indexación de cadena "falsa"dict['a']['e']
, donde'e'
está la nueva columna, ydict['a']
es un DataFrame que viene del diccionario.También tenga en cuenta que si sabe lo que está haciendo, puede cambiar la advertencia usando
pd.options.mode.chained_assignment = None
y luego usar una de las otras soluciones que se dan aquí.fuente
para insertar una nueva columna en una ubicación determinada (0 <= loc <= cantidad de columnas) en un marco de datos, solo use Dataframe.insert:
Por lo tanto, si desea agregar la columna e al final de un marco de datos llamado df , puede usar:
el valor puede ser una Serie, un número entero (en cuyo caso todas las celdas se rellenan con este valor) o una estructura tipo matriz
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.insert.html
fuente
Antes de asignar una nueva columna, si tiene datos indexados, debe ordenar el índice. Al menos en mi caso tuve que:
fuente
Sin embargo, una cosa a tener en cuenta es que si lo haces
esto será efectivamente una unión izquierda en el df1.index. Entonces, si desea tener un efecto de unión externa , mi solución probablemente imperfecta es crear un marco de datos con valores de índice que cubran el universo de sus datos y luego usar el código anterior. Por ejemplo,
fuente
Estaba buscando una forma general de agregar una columna de
numpy.nan
s a un marco de datos sin volverme tontoSettingWithCopyWarning
.De lo siguiente:
numpy
matriz de NaNs en líneaSe me ocurrió esto:
fuente
Para agregar una nueva columna, 'e', al marco de datos existente
fuente
En aras de la exhaustividad, otra solución más utilizando el método DataFrame.eval () :
Datos:
Solución:
fuente
Para crear una columna vacía
fuente
Lo siguiente es lo que hice ... Pero soy bastante nuevo en los pandas y realmente Python en general, así que no hay promesas.
fuente
Si obtiene el
SettingWithCopyWarning
, una solución fácil es copiar el DataFrame al que está intentando agregar una columna.fuente