Vou converter um Django QuerySet em um pandas da DataFrame
seguinte maneira:
qs = SomeModel.objects.select_related().filter(date__year=2012)
q = qs.values('date', 'OtherField')
df = pd.DataFrame.from_records(q)
Funciona, mas existe uma maneira mais eficiente?
Respostas:
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')))
A descrição acima é como eu faço a mesma coisa. A adição mais útil é especificar em quais campos você está interessado. Se for apenas um subconjunto dos campos disponíveis em que você está interessado, imagino que isso aumentaria o desempenho.
fonte
DataFrame.from_records()
funciona melhor, ou sejadf = pd.DataFrame.from_records(BlogPost.objects.all().values())
.BlogPost
suposto ser igual ao deleSomeModel
?Django Pandas resolve isso muito bem: https://github.com/chrisdev/django-pandas/
Do 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)
fonte
df = read_frame(qs, fieldnames=['age', 'wage', 'full_name'])
Converter o queryset em values_list () será mais eficiente em memória do que em values () diretamente. Visto que o método values () retorna um queryset de lista de dict (chave: pares de valor), values_list () retorna apenas uma lista de tupla (dados puros). Ele vai economizar cerca de 50% da memória, só precisa definir as informações da coluna quando você chamar pd.DataFrame ().
Eu testei isso em meu projeto com> 1 milhão de linhas de dados, o pico de memória foi reduzido de 2G para 1G.
fonte
Da perspectiva do Django (não estou familiarizado
pandas
), isso é bom. Minha única preocupação é que, se você tiver um número muito grande de registros, poderá ter problemas de memória. Se fosse esse o caso, algo na linha deste iterador queryset com eficiência de memória seria necessário. (O snippet conforme escrito pode exigir alguma reescrita para permitir o seu uso inteligente.values()
).fonte
.from_records()
e não usarlist()
vai eliminar a preocupação com a eficiência da memória..values()
retorna umValuesQuerySet
que armazena resultados em cache, portanto, para um conjunto de dados grande o suficiente, vai consumir bastante memória..from_records
sem a compreensão da lista para eliminar ambos os devoradores de memória. por exemplopd.DataFrame.from_records(qs[i].__dict__ for i in range(qs.count()))
. Mas você fica com aquela"_state"
coluna irritante quando terminar.qs.values()[i]
é muito mais rápido e limpo, mas acho que armazena em cache.Você pode 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()
fonte