将Django QuerySet转换为pandas DataFrame

Fra*_*uis 78 python django pandas

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

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

它有效,但是有更有效的方法吗?

lex*_*ual 70

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')))
Run Code Online (Sandbox Code Playgroud)

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

  • 使用'list()'似乎已被弃用(我在pandas 0.12上).使用`DataFrame.from_records()`效果更好,即`df = pd.DataFrame.from_records(BlogPost.objects.all().values())`. (32认同)
  • 如果这使用来自 OP 问题的名称会更清楚。例如,`BlogPost` 应该和他的 `SomeModel` 一样吗? (2认同)

小智 21

在 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) ## 有效,但内存使用量没有太大变化

方法二:
    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。


Dav*_*son 17

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)
Run Code Online (Sandbox Code Playgroud)

  • Django Pandas如何处理大型数据集?https://github.com/chrisdev/django-pandas/blob/master/django_pandas/io.py#L107这一行吓到我了,因为我认为这意味着整个数据集将立即加载到内存中. (8认同)
  • 对于那些在这个美好的未来中想知道我在说什么的人,这里有一个更永久的当时源链接:https://github.com/chrisdev/django-pandas/blob/bce1d59a552c81c91fb8aea7f522fde4a83d0159/django_pandas/io .py#L107 (2认同)

Dav*_*Eyk 2

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