我将 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')))
以上是我如何做同样的事情。最有用的补充是指定您感兴趣的字段。如果它只是您感兴趣的可用字段的子集,那么我想这会提高性能。
Django Pandas 巧妙地解决了这个问题:https ://github.com/chrisdev/django-pandas/
从自述文件:
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)
在 values_list() 上转换查询集将比直接在 values() 上更节省内存。由于方法 values() 返回字典列表(键:值对)的查询集,因此 values_list() 仅返回元组列表(纯数据)。它将节省大约 50% 的内存,只需要在调用 pd.DataFrame() 时设置列信息。
方法一: queryset = models.xxx.objects.values("A","B","C","D") df = pd.DataFrame(list(queryset)) ## 消耗大量内存 #df = pd.DataFrame.from_records(queryset) ## 有效,但内存使用没有太大变化 方法二: 查询集 = models.xxx.objects.values_list("A","B","C","D") df = pd.DataFrame(list(queryset), columns=["A","B","C","D"]) ##这样会节省50%的内存 #df = pd.DataFrame.from_records(queryset, columns=["A","B","C","D"]) ##不起作用。与数据类型崩溃的是查询集而不是列表。
我在我的项目中使用超过 100 万行数据对此进行了测试,峰值内存从 2G 减少到 1G。
你也许可以使用 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()
从 Django 的角度来看(我不熟悉pandas
),这很好。我唯一担心的是,如果您有大量记录,您可能会遇到内存问题。如果是这种情况,那么类似于这种内存高效查询集迭代器的东西将是必要的。(所写的片段可能需要一些重写以允许您巧妙地使用.values()
)。