Voy a convertir un Django QuerySet en pandas de la DataFrame
siguiente manera:
qs = SomeModel.objects.select_related().filter(date__year=2012)
q = qs.values('date', 'OtherField')
df = pd.DataFrame.from_records(q)
Funciona, pero ¿hay alguna forma más eficiente?
Respuestas:
import pandas as pd import datetime from myapp.models import BlogPost df = pd.DataFrame(list(BlogPost.objects.all().values())) df = pd.DataFrame(list(BlogPost.objects.filter(date__gte=datetime.datetime(2012, 5, 1)).values())) # limit which fields df = pd.DataFrame(list(BlogPost.objects.all().values('author', 'date', 'slug')))
Lo anterior es cómo hago lo mismo. La adición más útil es especificar los campos que le interesan. Si sólo está interesado en un subconjunto de los campos disponibles, supongo que esto aumentaría el rendimiento.
fuente
DataFrame.from_records()
funciona mejor, es decirdf = pd.DataFrame.from_records(BlogPost.objects.all().values())
.BlogPost
supone que es el mismo que el suyoSomeModel
?Django Pandas resuelve esto bastante bien: https://github.com/chrisdev/django-pandas/
Del README:
class MyModel(models.Model): full_name = models.CharField(max_length=25) age = models.IntegerField() department = models.CharField(max_length=3) wage = models.FloatField() from django_pandas.io import read_frame qs = MyModel.objects.all() df = read_frame(qs)
fuente
df = read_frame(qs, fieldnames=['age', 'wage', 'full_name'])
Convertir el conjunto de consultas en lista_valores () será más eficiente en memoria que en valores () directamente. Dado que el método values () devuelve un conjunto de consultas de una lista de dict (pares clave: valor), values_list () solo devuelve una lista de tuplas (datos puros). Ahorrará aproximadamente un 50% de memoria, solo necesita configurar la información de la columna cuando llame a pd.DataFrame ().
Probé esto en mi proyecto con> 1 millón de datos de filas, la memoria máxima se reduce de 2G a 1G.
fuente
Desde la perspectiva de Django (no estoy familiarizado
pandas
) esto está bien. Mi única preocupación es que si tiene una gran cantidad de registros, puede tener problemas de memoria. Si este fuera el caso, sería necesario algo similar a este iterador de conjunto de consultas de memoria eficiente . (El fragmento tal como está escrito puede requerir una reescritura para permitir un uso inteligente de.values()
).fuente
.from_records()
y no usarlist()
eliminará la preocupación por la eficiencia de la memoria..values()
devuelve unValuesQuerySet
que almacena en caché los resultados, por lo que para un conjunto de datos lo suficientemente grande, será bastante intensivo en memoria..from_records
sin la comprensión de la lista para eliminar ambos acaparadores de memoria. ejpd.DataFrame.from_records(qs[i].__dict__ for i in range(qs.count()))
. Pero te quedas con esa"_state"
columna molesta cuando terminas.qs.values()[i]
es mucho más rápido y limpio, pero creo que almacena en caché.Tal vez puedas usar model_to_dict
import datetime from django.forms import model_to_dict pallobjs = [ model_to_dict(pallobj) for pallobj in PalletsManag.objects.filter(estado='APTO_PARA_VENTA')] df = pd.DataFrame(pallobjs) df.head()
fuente