Revisamos de forma completamente cada escrito de nuestra página web con la meta de mostrarte siempre información veraz y certera.
Solución:
He aquí un par de sugerencias:
Utilizar date_range
para el índice:
import datetime
import pandas as pd
import numpy as np
todays_date = datetime.datetime.now().date()
index = pd.date_range(todays_date-datetime.timedelta(10), periods=10, freq='D')
columns = ['A','B', 'C']
Nota: podríamos crear un DataFrame vacío (con NaN
s) simplemente escribiendo:
df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs
Para hacer este tipo de cálculos para los datos, use un numpy array:
data = np.array([np.arange(10)]*3).T
Por lo tanto, podemos crear el DataFrame:
In [10]: df = pd.DataFrame(data, index=index, columns=columns)
In [11]: df
Out[11]:
A B C
2012-11-29 0 0 0
2012-11-30 1 1 1
2012-12-01 2 2 2
2012-12-02 3 3 3
2012-12-03 4 4 4
2012-12-04 5 5 5
2012-12-05 6 6 6
2012-12-06 7 7 7
2012-12-07 8 8 8
2012-12-08 9 9 9
¡NUNCA haga crecer un DataFrame!
TLDR; (Solo lee el texto en negrita)
La mayoría de las respuestas aquí le dirán cómo crear un DataFrame vacío y completarlo, pero nadie le dirá que es algo malo.
Aquí está mi consejo: Acumule datos en una lista, no en un DataFrame.
Use una lista para recopilar sus datos, luego inicialice un DataFrame cuando esté listo. Funcionará un formato de lista de listas o de lista de dictados, pd.DataFrame
acepta ambos.
data = []
for a, b, c in some_function_that_yields_data():
data.append([a, b, c])
df = pd.DataFrame(data, columns=['A', 'B', 'C'])
Ventajas de este enfoque:
-
Siempre es más barato agregar a una lista y crear un DataFrame de una sola vez que crear un DataFrame vacío (o uno de NaN) y agregarlo una y otra vez.
-
Las listas también ocupan menos memoria y son una estructura de datos mucho más liviana para trabajar.agregar y eliminar (si es necesario).
-
dtypes
se infieren automáticamente (en lugar de asignarobject
a todos ellos). -
A
RangeIndex
se crea automáticamente para sus datosen lugar de tener que tener cuidado de asignar el índice correcto a la fila que está agregando en cada iteración.
Si aún no está convencido, esto también se menciona en la documentación:
Agregar filas iterativamente a un DataFrame puede ser más intensivo desde el punto de vista computacional que una sola concatenación. Una mejor solución es agregar esas filas a una lista y luego concatenar la lista con el DataFrame original, todo a la vez.
Pero, ¿qué sucede si mi función devuelve tramas de datos más pequeñas que necesito combinar en una trama de datos grande?
Está bien, aún puede hacer esto en tiempo lineal al hacer crecer o crear una lista de python de DataFrames más pequeños, luego llamar pd.concat
.
small_dfs = []
for small_df in some_function_that_yields_dataframes():
small_dfs.append(small_df)
large_df = pd.concat(small_dfs, ignore_index=True)
o, más concisamente:
large_df = pd.concat(
list(some_function_that_yields_dataframes()), ignore_index=True)
Estas opciones son horribles
append
o concat
dentro de un bucle
Aquí está el error más grande que he visto de los principiantes:
df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
df = df.append('A': i, 'B': b, 'C': c, ignore_index=True) # yuck
# or similarly,
# df = pd.concat([df, pd.Series('A': i, 'B': b, 'C': c)], ignore_index=True)
La memoria se reasigna para cada append
o concat
operación que tienes. Combina esto con un bucle y tienes un operación de complejidad cuadrática.
El otro error asociado con df.append
es que los usuarios tienden a olvidar agregar no es una función en el lugar, por lo que el resultado debe volver a asignarse. También tienes que preocuparte por los dtypes:
df = pd.DataFrame(columns=['A', 'B', 'C'])
df = df.append('A': 1, 'B': 12.3, 'C': 'xyz', ignore_index=True)
df.dtypes
A object # yuck!
B float64
C object
dtype: object
Tratar con columnas de objetos nunca es bueno, porque los pandas no pueden vectorizar operaciones en esas columnas. Deberá hacer esto para solucionarlo:
df.infer_objects().dtypes
A int64
B float64
C object
dtype: object
loc
dentro de un bucle
yo también he visto loc
se usa para agregar a un DataFrame que se creó vacío:
df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
df.loc[len(df)] = [a, b, c]
Como antes, no ha asignado previamente la cantidad de memoria que necesita cada vez, por lo que la memoria vuelve a crecer cada vez que crea una nueva fila. es tan malo como append
y aún más feo.
Trama de datos vacía de NaN
Y luego, está la creación de un marco de datos de NaN y todas las advertencias asociadas con él.
df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5))
df
A B C
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
3 NaN NaN NaN
4 NaN NaN NaN
Crea un DataFrame de columnas de objetos, como los demás.
df.dtypes
A object # you DON'T want this
B object
C object
dtype: object
Agregar todavía tiene todos los problemas que los métodos anteriores.
for i, (a, b, c) in enumerate(some_function_that_yields_data()):
df.iloc[i] = [a, b, c]
La prueba está en el pudín
Programar estos métodos es la forma más rápida de ver cuánto difieren en términos de memoria y utilidad.
Código de evaluación comparativa para referencia.
Si simplemente desea crear un marco de datos vacío y llenarlo con algunos marcos de datos entrantes más tarde, intente esto:
newDF = pd.DataFrame() #creates a new dataframe that's empty
newDF = newDF.append(oldDF, ignore_index = True) # ignoring index is optional
# try printing some data from newDF
print newDF.head() #again optional
En este ejemplo, estoy usando este documento de pandas para crear un nuevo marco de datos y luego uso agregar para escribir en el nuevo DF con datos del antiguo DF.
Si tengo que seguir agregando nuevos datos a este nuevo DF desde más de un DF antiguo, solo uso un bucle for para iterar sobre pandas.DataFrame.append()
Te mostramos las reseñas y valoraciones de los usuarios
Te invitamos a añadir valor a nuestra información aportando tu experiencia en las aclaraciones.