Я собираюсь преобразовать Django QuerySet в pandas DataFrame
следующим образом:
qs = SomeModel.objects.select_related().filter(date__year=2012)
q = qs.values('date', 'OtherField')
df = pd.DataFrame.from_records(q)
Это работает, но есть ли более эффективный способ?
Ответы:
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')))
Выше показано, как я делаю то же самое. Наиболее полезным дополнением является указание, какие поля вас интересуют. Если это только подмножество доступных полей, которые вас интересуют, то это, как я полагаю, дало бы прирост производительности.
источник
DataFrame.from_records()
работ лучше, то естьdf = pd.DataFrame.from_records(BlogPost.objects.all().values())
.BlogPost
должно быть таким же, как у негоSomeModel
?Django Pandas решает это довольно четко: https://github.com/chrisdev/django-pandas/
Из 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)
источник
df = read_frame(qs, fieldnames=['age', 'wage', 'full_name'])
Преобразование набора запросов в values_list () будет более эффективным с точки зрения памяти, чем напрямую в values (). Поскольку метод values () возвращает набор запросов из списка dict (пары ключ: значение), values_list () возвращает только список кортежей (чистые данные). Это сэкономит около 50% памяти, просто нужно установить информацию о столбце при вызове pd.DataFrame ().
Я тестировал это в своем проекте с данными> 1 миллиона строк, пиковая память уменьшена с 2 ГБ до 1 ГБ.
источник
С точки зрения Django (с которой я не знаком
pandas
) это нормально. Меня беспокоит только то, что если у вас очень большое количество записей, вы можете столкнуться с проблемами памяти. Если бы это было так, то потребовалось бы что-то вроде этого итератора набора запросов с эффективным использованием памяти . (Фрагмент в том виде, в каком он был написан, может потребовать некоторой переписывания, чтобы его можно было использовать с умом.values()
).источник
.from_records()
и не использоватьlist()
устранит проблему эффективности памяти..values()
возвращает,ValuesQuerySet
который кэширует результаты, поэтому для достаточно большого набора данных это будет довольно интенсивно для памяти..from_records
без понимания списка, чтобы устранить обе проблемы с памятью. напрpd.DataFrame.from_records(qs[i].__dict__ for i in range(qs.count()))
. Но"_state"
когда вы закончите, у вас останется эта раздражающая колонка.qs.values()[i]
намного быстрее и чище, но я думаю, что он кеширует.Возможно, вы можете использовать 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()
источник