113

我将 Django QuerySet 转换为 pandas DataFrame,如下所示:

qs = SomeModel.objects.select_related().filter(date__year=2012)
q = qs.values('date', 'OtherField')
df = pd.DataFrame.from_records(q)

它有效,但有没有更有效的方法?

4

5 回答 5

120
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')))

以上是我如何做同样的事情。最有用的补充是指定您感兴趣的字段。如果它只是您感兴趣的可用字段的子集,那么我想这会提高性能。

于 2013-04-29T05:39:15.383 回答
27

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)
于 2015-05-01T16:25:15.653 回答
25

在 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。

于 2019-03-08T01:14:03.127 回答
2

你也许可以使用 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()
于 2015-03-17T17:12:14.670 回答
2

从 Django 的角度来看(我不熟悉pandas),这很好。我唯一担心的是,如果您有大量记录,您可能会遇到内存问题。如果是这种情况,那么类似于这种内存高效查询集迭代器的东西将是必要的。(所写的片段可能需要一些重写以允许您巧妙地使用.values())。

于 2012-09-05T18:28:43.527 回答